给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
不允许修改 链表。
//抄的
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *slow = head, *fast = head;
// 第一次相遇
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) break;
}
// 无环情况
if (!fast || !fast->next) return nullptr;
// 重置快指针并同步移动
fast = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
return slow; // 或 fast
}
};
很久没碰数学了,捯饬半天啥也没搞出来
slow走的距离为a+n(b+c)+b
fast走的距离为a+m(b+c)+b
fast-slow=slow=(m-n)(b+c)=a+n(b+c)+b
a = (m-2n)(b+c)-b=(m-2n-1)(b+c)+c
m-2n-1不一定为正数,为了看着舒服,可以写为
|a-c|=k(b+c)
根据这个可以得到,在快慢指针第一次相遇后,从head出发一个新的指针,与慢指针同一速度出发,必然相遇于环节点。
无论a和c谁比较大,小的那个指针走到环节点时,另一个必然刚好比其多k圈,并相遇。