原理
重画链表如下所示,线上有若干个节点。记蓝色慢指针为 slow,红色快指针为 fast。初始时 slow 和 fast 均在头节点处。
使 slow 和 fast 同时前进,fast 的速度是 slow 的两倍。当 slow 抵达环的入口处时,如下所示。
其中:
- head 和 A 的距离为 z z z
- 弧 AB (沿箭头方向) 的长度为 x x x
- 同理,弧 BA 的长度为 y y y
可得:
- slow 走过的步数为 z z z
- 设 fast 已经走过了 k k k 个环, k ≥ 0 k \geq 0 k≥0,对应的步数为 z + k ( x + y ) + x z + k(x+y) + x z+k(x+y)+x
以上两个步数中,后者为前者的两倍,整理可得
z
=
x
+
k
(
x
+
y
)
z = x + k(x+y)
z=x+k(x+y),替换如下所示。
此时因为 fast 比 slow 快 1 个单位的速度,且弧 BA 的长度为整数,所以再经过 y 个单位的时间即可追上 slow。
即 slow 再走
y
y
y 步,fast 再走
2
y
2y
2y 步。设相遇在 C 点,位置如下所示,可得弧 AC 长度为 y。
因为此前
x
+
y
x + y
x+y 为环长,所以弧 CA 的长度为
x
x
x。
此时我们另用一橙色指针 ptr (pointer) 指向 head,如下所示。并使 ptr 和 slow 保持 1 个单位的速度前进,在经过
z
=
x
+
k
(
x
+
y
)
z = x + k(x+y)
z=x+k(x+y) 步后,可在 A 处相遇。
再考虑链表无环的情况,fast 在追到 slow 之前就会指向空节点,退出循环即可。
算法实现
复杂度
时间: Θ ( n ) \Theta(n) Θ(n)
- 如果相交
- fast 和 slow 相遇时 slow 走过的距离 ≤ n \leq n ≤n,所以 fast 走过的距离 ≤ 2 n \leq 2n ≤2n
- ptr 走过的距离 < n < n <n
- slow 走过的距离 ≥ n \geq n ≥n 但 < < < fast 和 ptr 走过的距离之和。
- 如果不相交,fast 走过 n n n 步即结束
空间: Θ ( 1 ) \Theta(1) Θ(1)
推广
以下皆为个人所著,兼顾了职场面试和本硕阶段的学术考试。
点赞关注不迷路,祝各位早日上岸,飞黄腾达!