对链表进行旋转
题目
给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。
示例:将如下链表向右移动2位。
输入:head = [1,2,3,4,5], k = 2
输出:[4,5,1,2,3]
解决思路
- 第一步:初始时刻定义指针p指向head节点,然后让p指向链表的最后一个节点,并将链表收尾相连构成环。接着让p指向head节点。
- 第二步:将链表向右旋转k-1步,使指向head的指针p走到最终要输出的头节点的上一个节点(注意:设链表的长度为L,向右旋转k步即让指向head的指针p向右走L-k步)。
- 第三步:将链表从p的下一个节点处断开,p的下一个节点即为要返回的头节点。
代码
- C++代码
# include <stdio.h>
struct ListNode {
int val;
ListNode *next;
ListNode(): val(0), next(nullptr) {}
ListNode(int val): val(val), next(nullptr) {}
ListNode(int val, ListNode *next): val(val), next(next) {}
};
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if (nullptr == head || 0 == k) {
return head;
}
int step = 0; // 记录最终实际要走的步数
int num = 1; // 记录链表节点的个数
ListNode *p = head;
// 遍历链表节点,并将指针p指向链表的尾结点
while (p->next) {
p = p->next;
num += 1;
}
p->next = head; // 将链表构成环,此时p指向尾节点
p = head; // 让p指向头节点
step = k % num; // 若k大于num时,链表需要转整数圈,处理后,减少移动的步数,不需要转到一整圈
step = num - step - 1; // 先向右旋转k-1步(即指针向右走num-k-1步),让指针p指向最终要输出的头节点的上一个节点
while (step--) {
p = p->next; // 让指针p指向最终要输出的头节点的上一个节点
}
head = p->next; // 指针p的下一个节点即为要输出的头结点
p->next = nullptr; // 从p的下一个节点处断开链表
return head;
}
};
int main() {
ListNode *a = new ListNode(1);
ListNode *b = new ListNode(2);
ListNode *c = new ListNode(3);
ListNode *d = new ListNode(4);
ListNode *e = new ListNode(5);
ListNode *head = a;
a->next = b;
b->next = c;
c->next = d;
d->next = e;
printf("before rotate: ");
while (head) {
printf("%d ", head->val);
head = head->next;
}
printf("\n");
int k = 2;
head = a;
Solution *solution = new Solution();
ListNode *ret = solution->rotateRight(head, k);
printf("after rotate: ");
while (ret) {
printf("%d ", ret->val);
ret = ret->next;
}
return 0;
}
说明
- 对应LeetCode第61题。
- 链接:https://leetcode-cn.com/problems/rotate-list/