题目:输入k和链表的头结点,循环右移链表的后K个结点。
For example:
Given1->2->3->4->5->NULLand k =2,
return4->5->1->2->3->NULL.
思路:
1.首先要找链表的倒数第K个结点;
2.因循环右移的K个结点仍是按原来顺序排列,可考虑用一个先进先出的容器 即队列 将 后K个结点
存储,依次连接在链表首处;
3.但此解法空间复杂度为O(k);
4.将链表首尾相接成环,然后在第K个结点前的结点处断开即可;
因leetcode上测试用例中的k有大于length of list 的情况,故要先遍历一遍然后使k=k%(length of list),
时间复杂度仍为O(n).
还有一个方法,其他博客也有:
用快慢指针来解,快指针先走k步,然后两个指针一起走,当快指针走到末尾时,慢指针的下一个位置是新的顺序的头结点,这样就可以旋转链表了,自信满满的写完程序,放到OJ上跑,以为能一次通过,结果跪在了各种特殊情况,首先一个就是当原链表为空时,直接返回NULL,还有就是当k大于链表长度和k远远大于链表长度时该如何处理,我们需要首先遍历一遍原链表得到链表长度n,然后k对n取余,这样k肯定小于n,就可以用上面的算法了,代码如下:
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if(!head)return NULL;//特殊情况,链表为空
int size =0;
ListNode *cur = head;
while(cur){
cur = cur->next;
size++;
}
k = k%size;
ListNode *slow = head;
for(int i=0;i<k;i++){
fast = fast->next;
}
if(!fast) return head; //特殊情况,k的位置正好在链表末尾
fast = fast->next;
slow = slow->next;
}
fast->next=head; //环形链表
head = slow->next;//找到表头
slow->next = NULL;//断开链表
return head;
}
};
方法不难,用笔演算一下步骤就知道了思路