Algorithm 如何在链接列表中找到循环的起始节点?

Algorithm 如何在链接列表中找到循环的起始节点?,algorithm,floyd-cycle-finding,Algorithm,Floyd Cycle Finding,根据弗洛伊德的循环查找算法,乌龟和兔子相遇的点解释了链接列表中的循环性质 为了找到循环中的起始节点,我们将乌龟指针初始化为列表的开头,并开始将兔子和乌龟指针增加一个单位。它们相交的点表示循环的起始节点 请告诉我在给定的情况下它是如何工作的 链接列表如下所示: 1->2->3->4->5->6->7->8->3 好的,直接回答: 您提供的[编辑:链表,非序列]不包含任何周期。下面是将会发生的事情。 在算法的第一部分,乌龟和头发将分别从x1=2和x2

根据弗洛伊德的循环查找算法,乌龟和兔子相遇的点解释了链接列表中的循环性质

为了找到循环中的起始节点,我们将乌龟指针初始化为列表的开头,并开始将兔子和乌龟指针增加一个单位。它们相交的点表示循环的起始节点

请告诉我在给定的情况下它是如何工作的

链接列表如下所示:

1->2->3->4->5->6->7->8->3
好的,直接回答: 您提供的[编辑:链表,非序列]不包含任何周期。下面是将会发生的事情。 在算法的第一部分,乌龟和头发将分别从x1=2和x2=3开始。 然后它们将前进到x2=3和x4=5。 然后到x3=4和x6=7。 然后是x4=5和x8=3。 然后兔子将停止前进,因为x8之外没有任何东西,算法将产生没有找到循环的结果

下面我编译了一个小GIF,它显示了Floyd的循环查找应用于一个不同的序列,该序列确实包含循环

让我们看看

你把兔子和乌龟放在1的位置,让它们跑,兔子的速度是乌龟的两倍

在第0步,两者都是1。在第一步中,乌龟移动到2,兔子移动到3,依此类推

1 1
2 3
3 5
4 7
5 3
6 5
7 7 
所以兔子和乌龟在7点相遇

现在把乌龟放在最开始的位置,让它们以同样的速度再次奔跑

1 7
2 8
3 3 
因此,它们确实在周期的第一个要素上相遇了


这就是它在给定情况下的工作原理。

好的,让我们保持简单

假设你有两个跑步者A和B。A每一步向前移动1个节点,B移动2个节点

如果是循环列表,他们最终会相遇

当时

假设到目前为止A移动的距离是
m
,那么B移动的距离是
2m

还要注意

 m = a + b
2m = a + b + k * lengthOfLoop
因为对于B来说,它移动了A移动的任何距离,加上循环的
k
(一些我们不关心的数字)
a
是循环点之前的距离,
b
是循环点之后移动的距离a

然后我们有(经过一些数学)

现在我们把B放回列表的最前面,把他的速度降到1

对于B,它是远离循环点的
a
节点。对于A,他已经通过了
b
,并且根据上面的等式,他也离循环点
A
节点远


因此,在
a
更多步骤之后,a和B将在循环点再次相遇。

考虑两个指针:
快速指针(一次移动两个节点)和
慢速指针(一次移动一个节点)。两者都从链表的开头开始移动

一段时间后,
慢速指针进入循环,从头部移动k节点,此时
快速指针将移动列表头部的2k节点。因此,这意味着
快速指针
慢速指针
指向k节点

现在他们继续前进,直到他们在环路的某个地方相遇。当它们相遇时,它们将与循环开始时的
快速指针
慢速指针
的节点数完全相同(即循环的起始节点与
快速指针
慢速指针
相交的节点之间的距离为k元素(或节点)。 k也是循环的起始节点到链表头部的距离

因此,我们开始从头部移动一个指针,从
快速指针
慢速指针
的交汇点移动一个指针。由于循环起始节点距离这两个点k,因此它们将在循环起始节点的k第四步相遇
  • 假设你有一个长度为9的链表,把乌龟放在索引0,兔子放在索引1
  • 兔子应该以x2的速度移动,乌龟应该以x1的速度移动,这样下次它们移动时,兔子将处于指数3,乌龟将处于指数2
  • 它们继续这样移动,直到兔子身上的值等于乌龟身上的值
  • 此时,将兔子移回链表的最前面(这样兔子现在位于链表的最前面,乌龟位于它遇到兔子的索引/位置),这一次它应该只移动x1,与乌龟的速度相同
  • 再次开始移动兔子和乌龟,如前所述,兔子和乌龟应以x1的速度移动,这样,如果兔子和乌龟相遇的位置在索引6处,下一次移动应导致兔子在索引1处,乌龟在索引7处
  • 兔子和乌龟再次相遇的下一点是这个链表上循环的开始

  • 可能重复的(和各种其他问题)是的..我已经看到了,但是如果你看到第二个答案并应用上述情况,那么这个答案是不令人满意的。对于弗洛伊德的,你在序列中寻找一个循环。你给出的示例序列不包含循环。你能解释一下什么样的“循环性质”吗你在寻找,也许我们说的不是同一件事?很好的说明,但是,他的例子确实包含一个循环,杜德,我给出的例子包含一个循环。第8个节点的下一个指针包含第3个节点的地址。这不是一个循环吗?严格地说,数学上,你是对的-假设我们使用了一些映射函数contiNUANY获取下一个元素,即上一个元素的某个递归函数。但是,在实际中,如果链表是循环链接的,这只会起作用。@Algomorph:对不起,我一点也不知道。1分t
    a = k * lengthOfLoop - b