Floyd用于在链表中查找循环的算法,如何证明它将始终有效

时间:2013-11-12 18:56:52

标签: algorithm linked-list floyd-cycle-finding

我理解Floyd的循环检测算法的概念。它的结论是,如果乌龟的行进速度是野兔的两倍,如果乌龟在一个循环中有一个k米的起点,那么乌龟和野兔将在循环前达到k米。

在单链表的情况下,指针A的行进速度是指针B的两倍。这意味着如果它需要指针B k步到达循环的入口点(我们还不知道它在哪里),指针A已经在循环内具有k个节点的头部开始。因此,两个指针将在循环的入口点之前与k个节点相遇。因此,如果我们将指针B移回头指针并将指针A保持在会合点(现在两个指针都是远离入口点的k个节点),并以相同的速度移动它们,它们将在入口点处相遇循环。

如何证明该算法适用于以下边界情况?

  1. 最后一个节点循环回头部的链表。在这种情况下,头部起始值k是什么?
  2. 超长链表,1000个节点,最后有一个小循环,3个节点。指针A的起始位置为1000,这意味着当指针B到达循环的入口点时,A已经循环多次。
  3. 如果存在1个节点的循环怎么办?
  4. 这不是作业。面试官告诉我,如果我有一个小循环,这个算法将不起作用。他没有解释原因。

3 个答案:

答案 0 :(得分:5)

很明显,如果有指针,两个指针最终都会到达循环。让我们假设,循环的长度为N.我们可以在循环模N中计算位置。

现在说指针A位于位置a,指针B位于位置b。在s步之后,A将在+ 2s mod N处且B将在b + s mod N处。对于要满足的两个指针,我们必须具有

a+2s = b+s (mod N)
a+s = b (mod N)
s = b - a (mod N)

所以在b - a(mod N)步骤之后,两个指针会相遇。

答案 1 :(得分:2)

当然它适用于小循环。考虑两个节点的循环。那就是:

A => B => C => B

所以乌龟和兔子从A开始。下表显示了会发生什么:

Tortoise  Hare
   A       A
   C       B
   C       C

当只有两个节点时,乌龟总是在它开始的地方结束。因此,当兔子每次移动一个节点并最终赶上时,乌龟基本上会保持静止。

顺便说一句,当你只有一个节点的循环时,同样的事情发生了。也就是说,当节点自行循环时。

亨利的回答给出了数学证明。

答案 2 :(得分:1)

考虑一下:在n移动后,您可以确定两个指针都在循环中,或者其中一些指针结束。通过下一次n移动,您可以确定A和B将会遇到某些点,因为周期的大小为< = n,因为每一步都会使它们之间的差异减小为1。