Given a list, rotate the list to the right by k places, where k is non-negative.
Example:
Given 1->2->3->4->5->NULL and k = 2,
return 4->5->1->2->3->NULL.
本来以为是一道很简单的旋转链表的题目,但是写出来之后漏洞百出,要考虑的特殊情况很多,比如k=0,head为null,k远远超过链表长度的情况。最大的感悟:做leetcode一定要学正确的思路,然后一遍遍强化;错误总是无穷无尽,你不能在一遍遍试错中学习,因为这么做太慢了。
言归正传,最直接的思路是用两个指针,第一个先走k步,然后两个一起走,注意一定要考虑特殊情况
代码如下:
1 class Solution { 2 public: 3 ListNode *rotateRight(ListNode *head, int k) { 4 if (!head) return NULL; 5 int n = 0; 6 ListNode *cur = head; 7 while (cur) { 8 ++n; 9 cur = cur->next; 10 } 11 k %= n; 12 ListNode *fast = head, *slow = head; 13 for (int i = 0; i < k; ++i) { 14 fast = fast->next; 15 } 16 while (fast->next) { 17 fast = fast->next; 18 slow = slow->next; 19 } 20 fast->next = head; 21 fast = slow->next; 22 slow->next = NULL; 23 return fast; 24 /* 25 以上四行也可以这么写,但是当k=0,链表只有一个元素时会出错 26 ListNode *t = slow->next; 27 slow->next = NULL; 28 fast->next = head; 29 fast = slow->next; 30 */ 31 } 32 };
另一种方法更加直观一些,只遍历一遍链表,得到链表长之后收尾连接,在前进 n - n%k得到新的链表头
代码如下:
1 class Solution { 2 public: 3 ListNode *rotateRight(ListNode *head, int k) { 4 if (!head) return NULL; 5 int n = 1; 6 ListNode *cur = head; 7 while (cur->next) { 8 ++n; 9 cur = cur->next; 10 } 11 cur->next = head; 12 int m = n - k % n; 13 for (int i = 0; i < m; ++i) { 14 cur = cur->next; 15 } 16 ListNode *newhead = cur->next; 17 cur->next = NULL; 18 return newhead; 19 } 20 };