可以算作是一道谜语题
第一步仍然使用快慢指针法,找到第一次相遇点。
第二步设两个指针,一个从相遇点出发,另一个从原始起点出发,二者都是一次一步,当二者相遇时,所在的点即为环的入口.
第二步要会从数学上证明:
设进入环之前的直线距离为d,二者相遇时,慢指针在环上走过的距离是x,快指针绕环k(注意k必然>=1)圈外加x, 环的周长是C,则有:
d+x = (x+d+kC) / 2 => d+x = kC => d = (k-1)C+(C-x)
因此,第二步中,从起点出发的指针走过d时,从相遇点出发的的指针走过(k-1)C +(C-x),而C-x恰好是回到入口点出的长度,于是得证。
/**
* 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* dummy = new ListNode(0);
dummy->next = head;
ListNode* p1 = dummy;
ListNode* p2 = dummy;
bool mark = false;
while (p2!=NULL && p2->next!=NULL) {
p1 = p1->next;
p2 = p2->next->next;
if (p1 == p2) {
mark = true;
break;
}
}
if (mark == false) return NULL;
int cnt = 0;
p2 = dummy;
while (p2 != p1) {
p2 = p2->next;
p1 = p1->next;
++cnt;
}
return p1;
}
};