Given a list, rotate the list to the right by k places, where k is non-negative.
For example:
Given 1->2->3->4->5->NULL
and k = 2
,
return 4->5->1->2->3->NULL
.
這道旋轉鏈表的題和之前那道 Rotate Array 旋轉數組 很類似,但是比那道要難一些,因為鏈表的值不能通過下表來訪問,只能一個一個的走,我剛開始拿到這題首先想到的就是用快慢指針來解,快指針先走k步,然后兩個指針一起走,當快指針走到末尾時,慢指針的下一個位置是新的順序的頭結點,這樣就可以旋轉鏈表了,自信滿滿的寫完程序,放到OJ上跑,以為能一次通過,結果跪在了各種特殊情況,首先一個就是當原鏈表為空時,直接返回NULL,還有就是當k大於鏈表長度和k遠遠大於鏈表長度時該如何處理,我們需要首先遍歷一遍原鏈表得到鏈表長度n,然后k對n取余,這樣k肯定小於n,就可以用上面的算法了,代碼如下:
解法一
class Solution { public: ListNode *rotateRight(ListNode *head, int k) { if (!head) return NULL; int n = 0; ListNode *cur = head; while (cur) { ++n; cur = cur->next; } k %= n; ListNode *fast = head, *slow = head; for (int i = 0; i < k; ++i) { if (fast) fast = fast->next; } if (!fast) return head; while (fast->next) { fast = fast->next; slow = slow->next; } fast->next = head; fast = slow->next; slow->next = NULL; return fast; } };
這道題還有一種解法,跟上面的方法類似,但是不用快慢指針,一個指針就夠了,原理是先遍歷整個鏈表獲得鏈表長度n,然后此時把鏈表頭和尾鏈接起來,在往后走n - k % n個節點就到達新鏈表的頭結點前一個點,這時斷開鏈表即可,代碼如下:
class Solution { public: ListNode *rotateRight(ListNode *head, int k) { if (!head) return NULL; int n = 1; ListNode *cur = head; while (cur->next) { ++n; cur = cur->next; } cur->next = head; int m = n - k % n; for (int i = 0; i < m; ++i) { cur = cur->next; } ListNode *newhead = cur->next; cur->next = NULL; return newhead; } };