2020年12月8日 周二 天气晴 【不悲叹过去,不荒废现在,不惧怕未来】
剑指offer板块没有这道题,但是这道题其实和 Leetcode 142. 环形链表 II 是一样的。
假设:
f:fast走过的路程;
s:slow走过的路程;
b:走一圈环经过的路程;
a:从起点走到环入口经过的路程;
则有:
f = 2s (快指针每次走2步,路程刚好是慢指针的2倍)
f = s + nb (相遇时,刚好多走了n圈)
推出:s = nb
从head节点走到环的入口节点需要走 : a + nb, 而slow已经走了nb,那么slow再走a步就是入口了。同理,fast已经走了 2nb 步,再走a步也到达入口了。因此,让快指针(慢指针也行)从head开始走,慢指针从相遇的地方开始走,当它们都走了 a 步时,则会相遇。因为它们此时一个走了 a + nb 步,一个走了 a + 2nb 步,所以会在入口节点相遇。
代码如下:
/**
* 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 *fast = head, *slow = head;
while(fast && fast->next){
slow = slow->next;
fast = fast->next->next;
if(slow == fast) break;
}
// 如果 fast && fast->next 为真,说明 slow = fast,即它们相遇了
if(fast && fast->next){
fast = head;
while(fast!=slow){
slow = slow->next;
fast = fast->next;
}
return fast;
}
return nullptr;
}
};
参考文献
《剑指offer 第二版》
https://leetcode-cn.com/problems/linked-list-cycle-ii/solution/linked-list-cycle-ii-kuai-man-zhi-zhen-shuang-zhi-/