有关环形链表的思考
1.为什么快慢指针在环中一定会相遇,是否可能会错过永远追不上?
- 假设链表带环,两个指针最终都会进入环中,快指针先入环,慢指针后入环。当慢指针进环时,根据环的大小不同,快指针可能在环中已经走了
n
(n>0
)圈了,与快指针最好的情况下相差2个结点距离,最坏情况下相差1个环的距离,此时快慢指针继续往前走,两个指针每次移动,它们之间的距离就会缩小1个结点距离,并且不会出现错过套圈的情况,因此快指针一定会追上慢指针,快慢指针一定会相遇。
1.1 理论剖析证明:
-
假设条件:
- 链表带环。
- 两个指针(快指针和慢指针)都从链表的头开始移动。
- 快指针每次移动两步,慢指针每次移动一步。
-
快指针进入环:
- 由于快指针的移动速度比慢指针快,快指针会先进入环中。
-
慢指针进入环:
- 当慢指针进入环时,快指针可能已经在环中走了多圈。
-
最好情况和最坏情况:
- 最好情况:当慢指针进入环时,快指针刚好在其前方2个节点的位置。这样,快指针和慢指针只需要再各自移动2步和1步就会相遇。
- 最坏情况:当慢指针进入环时,快指针刚好在其前方整整一圈的位置。这样,快指针需要再走一整圈才能追上慢指针。
-
指针相遇:
- 不论初始位置如何,快指针每次移动都会比慢指针多靠近1个节点的距离(因为快指针每次移动两步,慢指针每次移动一步)。
- 由于环是封闭的,快指针最终一定会追上慢指针,两者相遇。
1.2 图解剖析证明:
- 设链表头结点到环入口处的距离为
a
,环的大小为C
, - 当慢指针
slow
走到环入口处时,快指针可能已在环中走了n
圈,此时令slow
距离fast
距离为m
,则fast
到slow
的距离为C-m
(因为快指针速度块,是快指针追击慢指针,所以fast
追击slow
的距离或者说真正距离实际上是C-m
), - 随着
slow
走1
步和fast
走2
步的继续,fast
和slow
之间的距离会逐渐减小,每次同时移动后它们的距离会减小1
个距离,
即C-m
,C-m-1
,C-m-2
,....
,3
,2
,1
,0
,最终会相遇, - 由于它们的速度差为1,所以不论环里面的结点个数是奇数,还是偶数,它们最终都会相遇。
2.慢指针slow走1步,快指针fast走3步,走4步…走N步,可不可以?
- 同样的,假设链表带环,快慢指针都会进入环中,当慢指针进环时,根据环的大小不同,快指针可能在环中已经走了
n
(n>0
)圈了。设链表头结点到环入口处的距离为a
,环的大小为C
,当慢指针slow
走到环入口处时,快指针可能已在环中走了n
圈,此时令slow
距离fast
距离为m
,则fast
到slow
的距离为C-m
(因为快指针速度块,是快指针追击慢指针,所以fast
追击slow
的距离或者说真正距离实际上是C-m
),如果慢指针走一步,快指针走N
步,那么快慢指针的速度差为N-1
,随着快慢指针的每次移动,它们之间的距离每次就会减少N-1
,即C-m-(N-1)
,C-m-2(N-1)
,C-m-3(N-1)
,...
,此时由于环内的节点奇偶个数不同,快慢指针的追击就存在套圈追不上的问题。
2.1具体剖析证明:
基本条件:
1. 链表存在环
2. 慢指针每次移动一个结点位置
3. 快指针每次移动N
个结点位置
4. 环的长度为C
分析:
-
快慢指针入环:
- 慢指针走到环的入口处时,快指针已经在环内走了
n
圈了(n>=0); - 令
slow
到fast
的距离为m,则fast
追击slow
的距离为C-m
;
- 慢指针走到环的入口处时,快指针已经在环内走了
-
快指针追上慢指针的可能:
- 快指针和慢指针的速度差为
N-1
,所以快慢指针每次的移动,致使在环内它们之间的距离每次会减少N-1
;
- 快指针和慢指针的速度差为
-
快慢指针追击过程:
- 当slow位于环的入口处时,
fast
与slow
之间的距离为C-m
; - 随着快慢指针的移动,它们之间的距离变为了
C-m-k(N-1)
。(k
是移动的次数);
- 当slow位于环的入口处时,
-
快指针追到慢指针的条件:
- 如果快指针追击到慢指针,那么它们之间的距离为
0
; - 快慢指针相遇时,需要找到一个k使得式子:
C-m-k(N-1) = 0
; - 将式子变形得到: k = C − m N − 1 k = \frac{C-m}{N-1} k=N−1C−m;
- 如果快指针追击到慢指针,那么它们之间的距离为
-
结论:
k
是一个整数- 如果
C-m
能够整除N-1
,那么快指针fast
就能追上慢指针slow
; - 如果
C-m
不能整除N-1
,那么快指针fast
就追不上慢指针slow
; - 那么快指针能否追击到慢指针,与环的长度
C
,快指针fast
每次移动的距离N
,slow
与fast
的距离m
有关 - 当
slow
走1
步,fast
走2
步时,它们的速度差为1,即N-1 = 1
。环的长度为C
,可能是奇数,也可能是偶数,m
同也是如此,所以C-m
的结果可奇可偶,那么此时C-m
必能整除N-1
,即快指针必能与慢指针相遇一处。 - 当
slow
走1步,fast走3
步时,它们的速度差为2
,即N-1 = 2
。那么要使C-m
能整除N-1
,就要求C-m
必须时偶数,所以此种情况不行。
-
分析结论:
- 如果
C - m
能够整除N - 1
,那么快指针fast
就能追上慢指针slow
。
- 如果
-
具体情况分析:
7.1 当 slow 走 1 步,fast 走 2 步时:- 它们的速度差为
1
,即N-1=1
。 - 无论环的长度
C
是奇数还是偶数,亦或是m
的值,C - m
的结果都可奇可偶数。 - 由于
N - 1 = 1
,所以C - m
无论奇偶都能被N - 1
整除。
小结论:当
slow
走1
步,fast
走2
步时,快指针fast
必能追上慢指针slow
。7.2 当 slow 走 1 步,fast 走 3 步时:
- 它们的速度差为
2
,即N-1=2
。 - 要使
C - m
能被N - 1
整除,C - m
必须是偶数。 - 如果
C
和m
的奇偶性相同(都是奇数或都是偶数),那么C - m
将是偶数。 - 如果
C
和m
的奇偶性不同(一个奇数一个偶数),那么C - m
将是奇数。
小结论:只有当C
和m
的奇偶性相同时,快指针fast
才能追上慢指针slow
。故如果此种情况下要求快指针能追上慢指针,就会有相应的限制。
7.3 当slow走1步,fast走4,5,6…步时,亦是如此,可能会有相应的限制。
- 它们的速度差为
3.为什么从快慢指针的相遇点,和链表头结点处同时继续向下走,最终会在环的入口处相遇
慢指针slow
到相遇点M
位置的距离为L+X
,快指针追上慢指针到达相遇点的位置的距离为L+X+nR
,因为快指针的速度时慢指针的2
倍,所以2(L+X) = L + X + nR,
变形得到L = nR - X
3.1具体剖析证明:
一.基本条件:
- 链表中存在环。
- 慢指针
slow
每次移动一个节点。 - 快指针
fast
每次移动两步。 - 环的大小为
R
。 - 链表头结点到环的入口处的距离为
L
。 - 从环的入口到快慢指针相遇点的距离为
X
。 - 快指针比慢指针多走了
n
圈环,其中n
是非负整数。
二.分析:
- 快慢指针相遇前的状态分析:
- 慢指针到达环的入口处时,快指针已经在环内走了
n
圈 - 当快指针和慢指针在环内相遇时,假设它们相遇的节点为
M
。 - 快慢指针最终相遇在m点,那么慢指针到达相遇点是走了
L+X
步 - 快指针到达相遇点
M
,走了L+X+nR
步,(L + X)
表示从链表头结点到相遇点M
的距离。nR
表示慢指针到达环入口处时,快指针可能已经绕环n
圈的距离。- 因此,
(L + X + nR)
表示慢指针从头结点到相遇点的距离加上快指针绕环n
圈的距离。
- 慢指针到达环的入口处时,快指针已经在环内走了
2.快慢指针相遇时的状态分析:
- 快慢指针在环内相遇后,都位于在M
点。
三.推导:
-
快指针和慢指针相遇时的距离关系:
1.1 因为快指针的速度时慢指针的2
倍:所以慢指针走过的距离的2
倍等于快指针走过的距离。
1.2 当快指针和慢指针在环内相遇时,快指针比慢指针多走了n
圈环的距离加上从环的入口到相遇点的距离X
。
1.3 公式表示:2 ∗ ( L + X ) = L + X + n R 2 * (L + X) = L + X + nR 2∗(L+X)=L+X+nR
变形得: L = n R − X L = nR - X L=nR−X
四.理解式子: L = n R − X L = nR - X L=nR−X:
- n的值可以是1,2,3,4,5,6,7…,n的值取决于环的大小,环越小,n的值越大
- 当n = 1时,相当于R较大,L较小,正好满足L= R- X,此时正好证明命题
- 当n ≠ \neq = 1时,可以将式子变形为L = (n - 1)R + R - X,相遇点转了n圈后,又向前走了X个距离,此时相遇点距离入环出的距离仍然是R - X,满足L = R - X;
四.总结:
- 由等式 2 * (L + X) = (L + X + nR) 中,我们推导出 L = nR - X。
- 这表明从链表头结点到环的入口的距离 L 等于快指针绕过环 n 圈的距离减去从环的入口到相遇点的距离 X。
- 由于两个指针以相同的速度移动,当一个指针到达环的入口时,另一个指针也会到达相同的点。