Description
给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL
示例 2:
输入: 0->1->2->NULL, k = 4
输出: 2->0->1->NULL
解释:
向右旋转 1 步: 2->0->1->NULL
向右旋转 2 步: 1->2->0->NULL
向右旋转 3 步: 0->1->2->NULL
向右旋转 4 步: 2->0->1->NULL
Input
输入包含两行,第一行为 2 个整数 n, kn,k (1 ≤ k ≤ n≤ 100000)用空格隔开,第二行为 n 个整数,用空格隔开,表示链表每一个节点的值
Output
输出单独的一行,即链表旋转后的结果,用空格隔开
Sample Input 1
5 2 1 2 3 4 5
Sample Output 1
4 5 1 2 3
Sample Input 2
3 4 0 1 2
Sample Output 2
2 0 1
解法:
0、定义链表的结点结构:结点中用int保存数字,用Node*指针保存下一个结点的地址。
1、读入并构建链表。其中将第一个读入的数字放入头结点,并记录下其地址。对后续读入的n-1个结点分别构建结点并连入链表。注意最后一个结点的指针需要设置为NULL。可以在构建完成后遍历输出链表,以检查是否读入出错。
2、进行链表旋转。链表旋转的过程就是在每一步中,将尾结点放到头结点的前面。而k次旋转操作也可以合并为将右侧的k个结点挂到头结点的前面,也可以视为将左侧的n-k个结点挂到尾结点的右侧。而如果操作次数k大于链表长度n就存在重复的操作,其中的整数*n个操作是互相抵消的。因此一共旋转的次数可以简化为k%n次,从而降低时间复杂度。
3、遍历并输出链表。
代码:
1 #include "bits/stdc++.h" 2 3 using namespace std; 4 5 struct Node { 6 int val; 7 Node *pnext; 8 }; 9 //遍历并输出节点 10 void print(Node *head) { 11 Node *thisNode = head; 12 while (thisNode) { 13 cout << thisNode->val << " "; 14 thisNode = thisNode->pnext; 15 } 16 } 17 18 int main() { 19 int n, k; 20 cin >> n >> k; 21 //读入头结点 22 Node *headNode = (Node *) malloc(sizeof(Node)); 23 cin >> headNode->val; 24 Node *lastNode = headNode; 25 //读入并构建剩余n-1个结点 26 for (int i = 1; i < n; i++) { 27 // create node 28 Node *p = (Node *) malloc(sizeof(Node)); 29 cin >> p->val; 30 lastNode->pnext = p; 31 lastNode = p; 32 } 33 lastNode->pnext = NULL; //尾结点设置为空 34 35 //print(headNode); //检查链表构建是否正确 36 37 k = k % n; //去除多余操作 38 39 Node *newTailNode = headNode; //取出左侧n-k个结点 40 for (int i = 1; i < n - k; i++) { 41 newTailNode = newTailNode->pnext; 42 } 43 Node *newHeadNode = newTailNode->pnext; 44 45 //将左侧n-k个结点挂到尾结点右侧,并将新的尾节点的指针设置为NULL 46 lastNode->pnext = headNode; 47 newTailNode->pnext = NULL; 48 49 print(newHeadNode); 50 51 return 0; 52 }