給定一個鏈表,旋轉鏈表,將鏈表每一個節點向右移動 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指針
再說這個題目的解題步驟以前先說說這個題目的理解,就是鏈表倒着數k個結點,而後斷開k+1和k個結點之間的聯接將其分紅兩個鏈表。而後將先後兩個鏈表調換一下位置從新鏈接起來。(固然當k大於鏈表長度的時候須要取模運算)code
1.計算鏈表的長度。
2.定義一個指針pPre指向頭結點,移動k步。
3.定義一個指針pCur指向頭結點,同時向前移動pPre和pCur指針直到pPre遍歷完整個鏈表,此時pCur即爲倒數第k個結點。
4.在第k個結點處斷開鏈表,再將先後兩個鏈表交換順序後從新鏈接起來。blog
ListNode* rotateRight(ListNode* head, int k) { if (head == NULL || head->next == NULL) { return head; } ListNode* pPre = head; int count = 0; while (pPre != NULL) { pPre = pPre->next; count++; } ListNode* pCur = head; pPre = head; for (int i = 0; i < k % count; i++) { pPre = pPre->next; } if (pPre != NULL) { while (pPre->next != NULL) { pPre = pPre->next; pCur = pCur->next; } pPre->next = head; head = pCur->next; pCur->next = NULL; } return head; }
改進版:數學
ListNode* rotateRight(ListNode* head, int k) { if (head == NULL || k == 0) { return head; } int count = 1; ListNode* p = head; while (p->next) { count++; p = p->next; } int left = count - k % count; p->next = head; for (int i = 0; i < left; ++i) { p = p->next; } head = p->next; p->next = NULL; return head; }
1.解題的關鍵是如何將題目轉化爲找到倒數第k個結點
2.另一個巧妙的地方是循環向前移動兩個指針的時候判斷的是pPre->next是否爲NULL,這樣能夠將pPre和pCur分別定位到斷開鏈表後的的最後一個結點上,方便斷開的鏈表進行聯接。
3.改進版是我在網上看到別人的思路實現的。首先統計整個鏈表的長度,同時將一個指針指向鏈表的最後一個結點,而後將鏈表首尾聯接起來,組成一個環,而後用數學的方法計算出正着數應該移動left步,而後將指向最後一個結點的指針移動left步,最後在這個位置將鏈表斷開即獲得結果。
有時候思路真的就是一層窗戶紙
List