结论:假设快指针fast与慢指针slow在环中相遇时所指向的节点为meet,则一个指针从meet开始走,另一个指针从head开始走,两个指针必定在 链表开始入环的节点begin 处相遇。
证明如下:
假设链表中环总长度为C,从begin到meet距离为X,从head到begin距离为L.
slow指针和fast指针相遇时,fast走的距离一定是slow的两倍,故有:
2 *(L + X) = L + N*C +X
这里N代表fast指针在环中转的圈数。
这里为什么是N * C,这是由于,如果L远大于C,则当slow走到begin时,fast可能已经在环里面转了很多圈了。
化简等式得:N*C - X = L; 即 (N-1)*C + C-X = L
即一个指针从meet出开始走,走(n-1)*C后,又回到meet,再走C-X到达begin,此时,正好另一个指针从head开始走,走L后到达begin,二者相遇。
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode* slow = head;
struct ListNode* fast = head;
while(fast && fast->next){
slow = slow->next;
fast = fast->next->next;
if(slow == fast){
//先找到meet节点
struct ListNode* meet = slow;
//当meet和head相遇时,必在环入口处
while(head != meet){
head = head->next;
meet = meet->next;
}
return head;
}
}
return NULL;
}