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