弗洛伊德循环检测算法| 确定周期的起点


32

我正在寻求帮助来了解弗洛伊德的循环检测算法。我已经对Wikipedia(http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare)进行了解释。

我可以看到算法如何检测O(n)时间的周期。但是,我无法想象这样一个事实,即一旦乌龟和野兔指针第一次相遇,就可以通过将乌龟指针移回起点,然后一次移动乌龟和野兔一步来确定周期的开始。他们初次见面的时间就是周期的开始。

有人可以提供一种解释,希望与维基百科上的解释有所帮助,因为我无法理解/可视化它?


3
我找到了关于stackoverflow的答案。如果有人在为我研究这个问题,谢谢。对于像我这样想要解释的人,请参考:stackoverflow.com/questions/3952805/… 为问题选择的答案进行了解释!
阿努拉格·卡普尔

嗨@Anurag。仅供参考,我在此处
Kyle,

您知道为什么fast变量或“野兔”需要以乌龟两倍的速度移动,而不是向前移动吗?
devdropper87

Answers:


47

您可以参考“在单链表中检测循环的开始”,摘录如下:

在此处输入图片说明

slowPointer会议之前经过的距离 =x+y

fastPointer会议之前经过的距离 = x + 2y + z=(x+y+z)+y

由于fastPointer到达的速度是的两倍slowPointer,因此到达集合点时,时间都是恒定的。因此,通过使用简单的速度,时间和距离关系(slowPointer行驶距离的一半):

2dist(slowPointer)=dist(fastPointer)2(x+y)=x+2y+z2x+2y=x+2y+zx=z

因此,通过移动slowPointer到链表的开始,并同时移动slowPointerfastPointer移动一个节点,它们都具有相同的覆盖距离

它们将到达循环列表中循环开始的位置。


2
在这里,您假设它们将旋转一圈后会合。在某些情况下(周期很小),在某些情况下可能会碰面。旋转。
Navjot Waraich

1
@JotWaraich图片不代表所有情况;但是逻辑仍然成立
denis631 '18

3
这是整个互联网上有关此算法的最直接的答案
Marshall X

7

我也将接受的答案视为其他地方的证明。但是,虽然它很容易理解,但却是不正确的。证明的是

x=z(这显然是错误的,并且由于绘制方式的原因,该图仅使其看起来合理)。

您真正想证明的是(使用与上面接受的答案中的图示相同的变量):

z=x mod (y+z)

L(y+z)是循环长度L

因此,我们要证明的是:

z=x mod L

或z与x相等(模L)

以下证明对我来说更有意义:

汇合点,M=x+y

k x + y L2(x+y)=M+kL,其中是某个常数。基本上,快速指针经过的距离是加上循环长度倍数kx+yL

x+y=kL

x=kLy

上面的等式证明与环路长度减去倍数相同。因此,如果快速指针从相交点或,则它将在循环的开始处结束。L y M x + yxLyMx+y


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.