Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.
You may not alter the values in the nodes, only nodes itself may be changed.
Only constant memory is allowed.
For example,
Given this linked list: 1->2->3->4->5
For k = 2, you should return: 2->1->4->3->5
For k = 3, you should return: 3->2->1->4->5
思路:在链表最前端添加一个新节点,命名为prenode。主要目的是为了前k个翻转后能比较容易地得到链表头。
维护3个指针,分别是pre, cur, nex。我们的思路是每k个一组进行处理。pre指针指向上一组k个节点中的最后一个(如果现在要处理的是第一组节点,则pre指向prenode节点,这也就是我们为什么要在表头前添加一个节点的原因,为了方便);cur指针指向该组节点的第一个;nex指针依次指向该组剩下的节点,一一进行逆转操作,一开始指向该组第二个也就是cur->next所指向的节点。逆转操作如下:
1. 将cur->next指向nex后面的一个节点。
2. 将nex->next指向pre后面的一个节点。
3. 将pre->next指向nex节点。
4. nex调到下一个节点(现在cur->next所指向的节点),开始下一次逆转操作。
代码如下:
1 cur->next = nex->next;
2 nex->next = pre->next;
3 pre->next = nex;
4 nex = cur->next;
这一步结束后的状态如下图
可以看出来,逆转操作每一步,都是把这一组后面的节点塞到这一组的最前面,并让上一组的最后一个节点指向它。当我们把这个过程重复k-1次(因为nex会依次指向该组第一个节点后的每一个节点,一共是k-1个节点)后,正好该组第k个节点就变成了最前面,并让上一组的最后一个指向了它,而该组的原本第一个节点此时也正好变成了最后一个节点,指向了下一组中的第一个。
1 class Solution {
2 public:
3 ListNode* reverseKGroup(ListNode* head, int k) {
4 if (head == NULL || k < 2) return head;
5 ListNode prenode(-1);
6 prenode.next = head;
7 ListNode *pre = &prenode, *cur, *nex = &prenode;
8 int num = 0;
9 while (nex = nex->next)
10 num++;
11 while (num >= k)
12 {
13 cur = pre->next;
14 nex = cur->next;
15 for (int i = 1; i < k; i++)
16 {
17 cur->next = nex->next;
18 nex->next = pre->next;
19 pre->next = nex;
20 nex = cur->next;
21 }
22 pre = cur;
23 num -= k;
24 }
25 return prenode.next;
26 }
27 };