当前:LC142 · 环形链表 II · 首次出现于 Day 11 · 路径:顶栏「56天打卡」→ 点击 LC 题号 → 逐题动画

LC142 · Linked List Cycle II · 链表

环形链表 II:相遇后再同步走,重逢即入口

相遇点不是入口。一个指针回头、两个都改走一步,下一次踩到的同一节点才是入口。

第一阶段与 LC141 相同:slow 一步、fast 两步,无环则 fast 先到 nil。有环则在环内相遇。设头到入口为 a,入口到相遇点为 b,环长为 c,由 2(a+b)=a+b+kc 得到 a=kc−b。第二阶段让一个指针回到 head,另一个留在相遇点,都改走一步:走 a 步后必然在入口重逢。时间 O(n),空间 O(1)。

时间 O(n)空间 O(1)结论先行 · 全文约 6 节
导读

这是 LeetCode 142. Linked List Cycle II。给你单链表头节点,若有环,返回入环的第一个节点;没有环返回 nil。入环点是「第一次走到一个 Next 已经指向过的节点」。

主例 3→2→0→−4,−4 的 Next 指回 2。入口是值为 2 的那个节点。对照无环 1→2→3,快指针会在尽头停下,返回 nil。单节点自环,入口就是它自己。

LC141 在相遇时就可以停,本题相遇点一般不是入口。缺的是把「头到入口」和「相遇点再走到入口」接成同一段距离。本文先用手跑完主例的相遇,再让一个指针回头,看他们为什么在 2 重逢。

先用快慢指针把相遇点跑出来

哈希表记下见过的地址,第一次重复就是入口,正确,空间线性。题目要 O(1) 空间,只能继续用快慢指针,但相遇本身只回答「有环」。

两人都从头出发,先移动再比较。slow 走 Next,fast 走 Next.Next。fast 自己或 Next 为空,说明有尽头,返回 nil。否则继续,直到两人踩到同一节点。

主例记四个地址:n3→n2→n0→n-4,且 n-4.Next=n2。第 1 轮慢到 n2、快到 n0;第 2 轮慢到 n0、快到 n2;第 3 轮慢走一格到 n-4,快走两格也到 n-4,相遇。慢走了 3 格,快走了 6 格,多走的 3 格正好一圈。演示把环上的相遇画出来,下一节要用这个点。

相遇点不是入口主例入口是 2,相遇在 −4。圈越长、入口越深,相遇点可以落在环上任意一格。把它当成答案会错。
fast 与 slow 在环内相遇
3
2
0
-4
绕圈
slow 与 fast 相遇于 0

一个回头,两个改走一步,重逢就是入口

设头到入口距离 a,入口到相遇点距离 b,环长 c。相遇时慢指针走了 a+b,快指针走了 a+b+kc(多绕了 k 圈),并且快的路程是慢的两倍:2(a+b)=a+b+kc,化简得 a=kc−b。kc−b 就是「从相遇点再走,先走完环上剩下的 c−b 到入口,再绕 k−1 整圈」。

所以把一个指针放回 head,另一个留在相遇点,双方都改成一次一步。走 a 步:回头的人刚好到入口;留在环上的人走完 kc−b,也到入口。他们踩到的第一个相同节点就是入口,不必数 a,也不必知道 c。

主例 a=1,b=2,c=3,k=1,a=3−2=1。slow 放回 3,fast 留在 −4。各走一步:slow 到 2,fast 从 −4 回到 2,重逢。演示从「slow 回 3、fast 停在环上」开始同步,最后一帧停在入口 2。无环时第一阶段已经返回,不会走进这一段。

slow 回 head,fast 留原地,同步 1 步
3
2
0
-4
绕圈
slow 回 3,fast 停 0

Go:相遇后同步找入口

solution.goGo
func detectCycle(head *ListNode) *ListNode {
slow, fast := head, head
for fast != nil && fast.Next != nil {
slow = slow.Next
fast = fast.Next.Next
if slow == fast {
slow = head
for slow != fast {
slow = slow.Next
fast = fast.Next
}
return slow
}
}
return nil
}

1出发时两人都在 head,必须先走再比,否则空环、无环都会被误判成入口在头。

2fast 不够两格就返回 nil。这是无环的唯一出口。

3相遇之后 slow 回头,fast 留在相遇点。主例是 −4。

4双方一步一步走。主例一步后都到 2,内层循环一次都不跑也会在入口相等——若 a=0,头结点就是入口,回头后立刻相等。

5比较的是节点地址。值相同的两个节点不是同一个入口。

总结

先相遇证明有环,再回头同步。主例第三轮遇在 −4,一步之后重逢于入口 2。

  • 相遇点一般不是入口。公式 a=kc−b 才把「从头走」和「从相遇点走」接成同一段。
  • 第二阶段两人都走一步,不要再让 fast 走两步,否则对不上 a。
  • 无环在第一阶段就被 fast 走到空拦截。空间始终两个指针。
同族题目
LC141环形链表LC287寻找重复数(同款数学)LC160相交链表