我知道乌龟和兔子相遇的地方标志着一个循环的存在,但是当我们将乌龟移动到链表的开头并保持兔子在相遇的地方,然后两个指针都每次向前移动一步时,它们如何会聚到循环的起点呢?
我知道乌龟和兔子相遇的地方标志着一个循环的存在,但是当我们将乌龟移动到链表的开头并保持兔子在相遇的地方,然后两个指针都每次向前移动一步时,它们如何会聚到循环的起点呢?
让我用自己的话来澄清在Wikipedia - Tortoise_and_hare提供的循环检测算法。
它是如何工作的
让我们假设有一只乌龟和一只兔子(指针的名称),它们指向具有循环的列表的开头,就像上面的图表中一样。
让我们假设如果我们每次将乌龟移动1步,兔子移动2步,它们最终会在某个点相遇。首先让我们证明这个假设是正确的。
该图说明了一个具有循环的列表。循环长度为n
,我们最初距离循环m
步。此外,假设当乌龟总共走i
步时,它们相遇的地方距离循环开始k
步。 (到那时,兔子已经走了2i
步。)
以下两个条件必须成立:
1) i = m + p * n + k
2) 2i = m + q * n + k
2 ( m + p * n + k ) = m + q * n + k
=> 2m + 2pn + 2k = m + nq + k
=> m + k = ( q - 2p ) n
在给定的列表中,m
、n
、k
、p
、q
中,前两个是属性。如果我们能够展示至少有一组值使得方程成立,即k
、q
、p
取值的解集不为空,则说明假设是正确的。
下面是这样一组解:
p = 0
q = m
k = m n - m
m + k = ( q - 2p ) n
=> m + mn - m = ( m - 2*0) n
=> mn = mn
i
是i = m + p n + k
=> m + 0 * n + mn - m = mn
k
步)。m
是什么。m+k
步,乌龟必须到达他们最初相遇的地点(距离循环开始k
步-见图)。m+k=(q-2p)n
。m+k
步是循环长度n
的倍数,因此在此期间,兔子将经过循环(q-2p
)次,并回到相同的点(距离循环开始k
步)。m + k
步,而是只让它们移动m
步,那么乌龟将到达循环的起点。兔子还差k
步就完成(q-2p
)个旋转。由于它在循环开始时就向前迈了k
步,因此兔子必须到达循环的开始处。m
步后到达循环,它永远看不到已经在循环中的兔子)。m
。当然,算法不需要知道什么是m
。它将同时每次使乌龟和兔子向前移动一步,直到它们相遇。会面点必须是循环的开始,步数必须是到循环开始的距离(m
)。假设我们知道列表的长度,我们也可以通过将列表长度减去m
来计算循环的长度。m + k =(q-2p)n
。但是,当兔子的速度是乌龟的两倍时,才得出了该方程式。现在它们以相同的速度移动,这个方程式仍然成立吗? - Hazem这是弗洛伊德的循环检测算法。你问的是算法的第二个阶段——一旦找到一个在循环中的节点,如何找到循环的起点?
在Floyd算法的第一部分,兔子每走一步,乌龟就走两步。如果乌龟和兔子相遇,则存在一个循环,并且相遇点是循环的一部分,但不一定是循环中的第一个节点。
当乌龟和兔子相遇时,我们已经找到了最小的i(乌龟走过的步数),使得Xi = X2i。让mu表示从X0到循环的开头所需的步数,lambda表示循环的长度。然后有i = mu + alambda,而2i = mu + blambda,其中a和b是整数,表示乌龟和兔子绕循环走了几次。将第一个方程式从第二个方程式中减去得到i =(b-a)* lambda,因此i是lambda的整数倍。 因此,Xi + mu = Xmu。Xi表示乌龟和兔子相遇的点。如果将乌龟移回起始节点X0,并让乌龟和兔子以相同的速度继续前进,那么在走完额外的mu步之后,乌龟将到达Xmu,而兔子将到达Xi + mu = Xmu,因此第二个相遇点表示循环的起点。
i
在循环的某一点上,所以我认为等式应该是i = mu + k + a*lambda
和2i = mu + k + b*lambda
,其中k
是从循环开始到相遇点的步数。不过,两个方程的差是相同的。 - Ivan Xiao老僧的简单而未受赞誉的答案解释了当快速跑者仅完成一次完整循环时如何找到循环。在这个答案中,我将解释当快速跑步者在慢速跑步者进入循环之前多次运行该循环的情况。
假设在慢跑和快跑者相遇之前,快跑者已经跑了m次循环。这意味着:
由于快跑者的速度是慢跑者的两倍,并且他们已经以相同的时间奔跑,这意味着如果我们将慢跑者奔跑的距离加倍,就会得到快跑者奔跑的距离。因此,
解决方案为x:
x = (m-1)(y+z)+z
在实际情况中,这意味着x=(m-1)完整的循环次数+额外的距离z。
因此,如果我们将一个指针放在列表的开头,将另一个指针留在相遇点,然后以相同的速度移动它们,将导致在循环指针完成m-1个循环运行之后,它们恰好在循环开始处相遇。
非常简单。您可以从相对速度的角度来考虑。如果兔子移动两个节点,而乌龟移动一个节点,则相对于乌龟,兔子移动了一个节点(假设乌龟静止不动)。因此,如果我们在循环链接列表中移动一个节点,我们肯定会再次在那个点相遇。
在找到循环链接列表内的连接点后,现在问题被缩小为查找两个链接列表问题的交点。
方法:
有两个指针:
如果这两个指针相遇,证明存在环。一旦它们相遇,一个节点将指向头部,然后两个节点每次移动一个节点。它们将在循环的开始处相遇。
原理: 当两个人走在一个圆形跑道上时,其中一个人的速度是另一个人的两倍,他们会在哪里相遇?正好回到起点。
现在,假设快跑者在n
步圆周中领先k
步。他们将在哪里相遇?恰好在n-k
步处。当慢跑者走了(n-k)
步时,快跑者将走k+2(n-k)
步。
(也就是说,k+2n-2k
步即2n-k
步) 即(n-k)
步(路径是圆形的,我们不关心他们相遇后走了多少圈;我们只关心他们相遇的位置)。
那么快跑者是如何领先k
步的呢?因为慢跑者需要走那么多步才能到达循环的起点。所以循环的起点距离头节点有k步。
注:两个指针相遇的节点距离循环的起点(在循环内)有k
步,头节点也距离循环的起点有k
步。因此,当我们让这些节点平均每次前进1步时,它们将在循环的起点处相遇。
我认为这很简单。如果有任何不明确的地方,请告诉我。
在第一次碰撞时,乌龟向前移动了m+k步,如上所示。兔子比乌龟快两倍,因此兔子向前移动了2(m+k)步。从这些简单的事实中,我们可以得出以下图表。
此时,我们将乌龟移到起点并宣布兔子和乌龟必须一次移动一步。根据定义,经过m步后,乌龟将位于循环的起点。而兔子会在哪里呢?
兔子也将位于循环的起点。这一点在第二个图表中很明显:当乌龟被移到起点时,兔子正好进入其最后一个循环的k步。经过m步之后,兔子将完成另一个循环并与乌龟相撞。
使用高中物理101/运动学讲座中教授的相对速度概念,提供一个简单的解释。
假设从链表开始到循环开始的距离是 x
。我们将循环的开始称为点 X
(大写 - 见上图)。同时,我们假设循环的总长度是 N。
兔子的速度 = 2 * 乌龟的速度。因此分别为 1 跳/秒
和 2 跳/秒
当乌龟到达循环的起点 X
时,兔子必须在图中的点 Y
处再向前 x
跳(因为兔子走的路程是乌龟的两倍)。
因此,从 X 到 Y 沿顺时针方向剩余的弧长为 N-x
。这也是兔子和乌龟相遇时它们之间要走的相对距离。假设这个相对距离需要时间 t_m
来走完。相对速度为 (2 跳/秒 - 1 跳/秒)
,即 1 跳/秒
。因此,使用相对距离 = 相对速度 × 时间,我们得到,t
= N-x
秒。因此,乌龟和兔子都需要 N-x
的时间到达相遇点。
现在,在 N-x
秒的时间内,以 1 跳/秒
的速度移动,之前在点 X
的乌龟将跳 N-x 次,到达相遇点 M
。因此,相遇点 M
距离点 X
顺时针方向有 N-x
跳的距离 = > 这进一步意味着,从点 M
到 X
顺时针方向还剩下 x
的距离。
但是,x
也是从链表开始到点 X
的距离。
现在,我们不关心 x
对应的跳数是多少。如果我们把一个乌龟放在 LinkedList 的起点,另一个乌龟放在相遇点 M
并让它们跳/走,那么它们会在点 X
相遇,这就是我们需要的点(或节点)。
取两个指针(1 =乌龟和2 =兔子),从头部(O)开始,1的步长为1,2的步长为2。思考当1到达该循环的起始节点(A)时的瞬间。
我们想要回答以下问题“当1在A时,2在哪里?”。
因此,OA = a
是自然数(a >= 0
)。但它可以用以下方式写成:a = k*n + b
,其中a,k,n,b为自然数
:
n
=周期长度k >= 0
=常量0 <= b <= n-1
这意味着b = a % n
。
例如:如果a = 20
且n = 8
=>k = 2
并且b = 4
,因为20 = 2*8 + 4
。
1覆盖的距离为d = OA = a = k*n + b
。但是同时,2覆盖了D = 2*d = d + d = OA + d = OA + k*n + b
。这意味着当2在A时,它必须覆盖k*n + b
。正如您所看到的,k
是圈数,但是在那些圈之后,2将离A有b远。因此,我们找到了当1在A时,2在哪里。让我们称那个点为B
,其中AB = b
。
现在,我们将问题简化为一个圆。问题是“会面的地方在哪里?”。那个C在哪里?
在每个步骤中,2通过1
(假设为米)减少与1
的距离,因为1
与1
之间的距离越来越远,但同时2
通过2
逐渐接近1
。
因此,当1和2之间的距离为零时,它们相交。这意味着2减少了n - b
的距离。为了实现这一点,1将进行n - b
步,而2将进行2*(n - b)
步。
因此,交点将在A的n - b
处(顺时针方向),因为这是1遇到2