题目:对一个单向链表,如有环,返回环的起始节点,如果没环,返回NULL
分析:在Cycle I部分,我们就讨论了如何判断链表是否有环,即通过快慢指针的相遇来判断。那么如何找到起始点呢?
首先,假设链表需要走a个节点进入环,走b个节点相遇,如图所示:
那么慢指针走了a+b, 快指针走了a+b + c + b,环长b+c
所以i
a+b = (a + b + c + b)/2 (快指针走的速度是慢指针的2倍)
得a = c
那么在快慢指针相遇后,只要把一个指针再指回head,另一个指针位置不变,然后每个指针一次走一步,走c的长度后自然就相遇,且相遇点在环的初始位置。
那么如果2个指针相遇时,已经走过环了,又是什么情况呢?
这种情况下,c' = k*(b+c),即已经走了k圈,那么慢指针走了k-1圈,抵消掉后还是一样的。
答案:
/**
* 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) {
ListNode *slow = head;
ListNode *fast = head;
bool flag = false;
while(fast!= NULL && fast->next != NULL){
slow = slow->next;
fast = fast->next->next;
if (slow == fast){
flag = true; // has meet
break;
}
}
if (!flag)
return NULL;
slow = head;
while(slow!= fast){
slow = slow->next;
fast = fast->next;
}
return slow;
}
};