Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.
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
Note:html
先分析题目的几个要求:node
分析可知,题目要求实现两个功能,一个是如何实现每k个节点一组;一个是翻转节点。python
这两个功能所用的方法能够自由组合。less
分组用递归完成:
定义节点lCur
记录分组结束位置的下一个节点,经过k循环来找到每一个lCur
;利用节点head
记录每一个分组的开始位置。翻转从head
到lCur
之间的节点,完成一组节点的翻转,获得一组新的节点lHead
。此时节点head
已经到了分组的最后一位,从后面接上递归调用下一分组获得的新节点lHead
,并返回新节点。
翻转用头插法完成(实现方法见Tips):
头插法以链表1->2->3->4->5为例子,假设k=5,完成以下图过程:
this
分组用循环完成,翻转用记录节点完成(实现方法见Tips)。
以链表1->2->3->4->5为例子,假设k=4,完成以下过程:
2->1->3->4->5
3->2->1->4->5
4->3->2->1->5
如上是4个一组的节点翻转,每行表明一次循环。code
节点的翻转有两种方法htm
新建一个虚拟节点dummy
,并保证虚拟节点链接链表的头节点。每当遍历到一个节点时,就把它链接到虚拟节点的下一个节点(整个链表的头部)。定义pCur
为当前要翻转的节点,过程以下:blog
//Step1:新建一个节点记录下一个要翻转的节点 ListNode* pNext = pCur->next; //Step2:将pCur置于整个节点的头部(即已经翻转好的节点的头部,完成翻转) pCur->next = dummy->next; //Step1:更新虚拟节点dummy的指向,使其指向链表的头节点 dummy->next = pCur; //Step4:更新当前节点,将其置于下一个要翻转的节点 pCur = pNext;
翻转的过程如图所示(以要翻转的节点的值为3为例):
递归
pCur
表示当前要翻转的节点,pPre
表示当前要翻转的前一个节点(也是已经完成翻转操做的最后一个节点),一次翻转过程(一次循环)以下:ip
// Step1:pPre链接下一个要翻转的节点 pPre->next = pCur->next; // Step2:pCur节点链接已经翻转好的节点(翻转当前节点) pCur->next = dummy->next; // Step3:更改虚拟节点的链接,使它指向已经翻转好的节点 dummy->next = pCur; // Step4:pCur指向下一个要翻转的节点 pCur = pPre->next;
翻转的过程如图2所示:
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* reverseKGroup(ListNode* head, int k) { ListNode* lCur =head; //该节点用于记录每组节点结束后的下一个节点 //循环找到每组结束的下一个节点 for(int i= 0 ; i < k; i++){ if(lCur == nullptr) return head; lCur = lCur->next; } ListNode* lHead = reverseOneGroup(head,lCur); head->next = reverseKGroup(lCur, k); return lHead; } /** * @Description:头插法实现一组节点内的翻转 * lHead:当前一组节点的头节点 * lTail:当前一组节点结束位置的下一个节点 */ ListNode* reverseOneGroup(ListNode* lHead, ListNode* lTail){ ListNode* dummy = new ListNode(-1); ListNode* lCur = lHead; while(lCur != lTail){ ListNode* lNext = lCur->next; lCur->next = dummy->next; dummy->next = lCur; lCur = lNext; } return dummy->next; } };
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* reverseKGroup(ListNode* head, int k) { //特殊状况 if(head == nullptr || k ==1) return head; //辅助的虚拟节点 ListNode* dummy = new ListNode(-1); //当前节点的上一个节点 ListNode* lPre = dummy; //当前节点 ListNode* lCur = head; dummy->next = head; int count = 0; //记录长度 while(lCur != nullptr){ count ++; if(count % k ==0){ lPre = reverseOneGroup(lPre, lCur->next); lCur = lPre->next; } else{ lCur = lCur->next; } } return dummy->next; } /** * @Description:记录节点法实现一组节点内的翻转 * lPre:当前一组节点的上一个节点 * lNext:当前一组节点的下一个节点 */ ListNode* reverseOneGroup(ListNode* lPre, ListNode* lNext){ ListNode* lEnd = lPre->next; ListNode* lCur = lEnd->next; while(lCur != lNext){ lEnd->next = lCur->next; lCur->next = lPre->next; lPre->next = lCur; lCur = lEnd->next; } return lEnd; } };
[1] https://www.cnblogs.com/byrhuangqiang/p/4311336.html
[2] https://www.cnblogs.com/grandyang/p/4441324.html