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

时间:2012-06-04 11:42:40

标签: algorithm floyd-cycle-finding

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

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

请告诉我它如何适用于特定情况。

链接列表如下:

1->2->3->4->5->6->7->8->3

5 个答案:

答案 0 :(得分:15)

让我们看看。

你将兔子和乌龟定位在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 

所以他们确实在周期的第一个元素中遇到过。

这就是给定情况的工作原理

答案 1 :(得分:14)

好的,让我们保持简单。

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

如果它是循环列表,它们最终会相互见面。

当时

说A到目前为止移动的距离是m,所以对于B来说它是2m

另请注意

 m = a + b
2m = a + b + k * lengthOfLoop

因为对于B,它移动了A移动的任何距离,加上k(我们不关心的一些数字)的循环。 a是循环点之前的距离,b是循环点之后移动的距离A.

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

a = k * lengthOfLoop - b

现在我们把B放回到列表的头部,然后将速度降低到1。

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

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

答案 2 :(得分:5)

好的,直接回答: 您给出的[编辑:链接列表,而不是序列]不包含循环。这是将要发生的事情。 在算法的第一部分中,乌龟和头发将分别从x1 = 2和x2 = 3开始。 然后他们将前进到x2 = 3和x4 = 5。 然后到x3 = 4和x6 = 7。 然后到x4 = 5和x8 = 3。 然后野兔将停止前进,因为除了x8之外没有任何东西,算法将产生没有发现的循环。

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

Floyd's algorithm in action.

答案 3 :(得分:0)

考虑两个指针:fast pointer(一次移动两个节点)和slow pointer(一次移动一个节点)。两者都从链表头开始移动。

一段时间后,slow pointer从头部进入 k 节点的循环,此时fast pointer将会走 2k 个节点列表的负责人。因此,这意味着fast pointer指向slow pointer k '节点。

Example: (fig 1)

现在他们继续前进,直到他们在循环中遇到某个地方。当它们相遇时,它们将远离循环的开始,与循环开始时fast pointer的{​​{1}}完全相同的节点数(即循环起始节点的距离)来自slow pointerfast pointer相遇的节点是 k 元素(或节点)。 k 也是循环起始节点与链表头部的距离。

(fig 2)

因此,我们开始从头部移动一个指针,从slow pointerfast pointer的会合点移动一个指针。由于环路起始节点的距离从这两点都 k ,因此它们将在环路的开始节点处的 k 步骤中相遇

答案 4 :(得分:0)

  • 假设您有一个长度为 9 的链表,将乌龟放在索引 0 处,将兔子放在索引 1 处。
  • 兔子应该以 x2 的速度移动,乌龟以 x1 的速度移动,这样它们下次移动时,兔子的索引为 3,乌龟的索引为 2
  • 他们继续以这种方式移动,直到兔子的价值等于乌龟的价值。
  • 此时,将野兔移回链表的头部(这样野兔现在在链表的头部,乌龟在它遇到野兔的索引/位置),这次它应该只移动 x1,与乌龟的速度相同。
  • 再次开始移动兔子和乌龟,如前所述,兔子和乌龟应该以 x1 的速度移动,这样如果兔子和乌龟相遇的位置在索引 6 处,则应该导致下一步移动兔子的索引为 1,乌龟的索引为 7。
  • 兔子和乌龟再次相遇的下一点是这个链表上循环的开始。