Given a linked list, return the node where the cycle begins. If there is no cycle, return null
.
Note: Do not modify the linked list.
Follow up:
Can you solve it without using extra space?
思路:
1.判断是否有环,见【Linked List Cycle】。
使用一个快指针fast和一个慢指针slow,快指针的速度是慢指针的2倍,如果fast指针能追上慢指针slow,这代表有环存在。因为两个指针的速度相差1,所以有环的话一定可以追上。
2.假设相遇时slow走了t步,这时fast走2t步。再设的环的结点数(也即slow的走一圈的步数)为tC,非环的结点数为tN。
则有:2t - tN = t - tN + i*tC,其中i指fast指针在环经过i圈后追上slow的。
整理有:t = i*tC,即slow走的步数为环结点的整数倍。
3.求tC。让flow和fast接着跑,再次相遇的步数即为tC。
4.重设slow = fast = head,让fast先走tC步
5.然后让slow和fast都以一次一步的速度走,相遇时的位置即为环的开始位置。
再思考:
其实第三步可以不用做,我们可以t即可。因为已经是tC的倍数。
这时,接着第2步。
令fast回到原点,执行上述第5步即可。
code:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(NULL == head) return NULL;
ListNode *slow, *fast;
fast = slow = head;
int isCircle = false;
while(slow && fast && fast->next) {
t1++;
slow = slow->next;
fast = fast->next->next;
if(fast == slow)
{
flag = true;
break;
}
}
if(!isCircle) return NULL;
fast=head;
while(fast != slow) {
slow = slow->next;
fast = fast->next;
}
return slow;
}
};