为什么Floyd的循环查找算法在某些指针增量速度下失败?

时间:2017-06-21 19:50:10

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

考虑以下链接列表:

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

以上列表的循环如下:

[4->5->6->7->8->9->4]

在白板上绘制链接列表,我尝试手动解决不同的指针步骤,看看指针是如何移动的 -

(slow_pointer_increment, fast_pointer_increment)

因此,不同情况的指针如下:

(1,2), (2,3), (1,3)

前两对增量 - (1,2)和(2,3)工作正常,但当我使用该对(1,3)时,算法似乎不适用于这对。是否有一个规则,我们需要增加多少步骤让这个算法保持为真?

虽然我搜索了较慢和较快指针的各种增量步骤,但到目前为止我还没有找到一个相关的答案,说明为什么它不适用于此列表中的增量(1,3)。

2 个答案:

答案 0 :(得分:1)

如果指针增量和循环长度之间的差异是互质的(即它们的最大公约数必须为1),则只保证算法在任何位置找到一个循环。

对于一般情况,这意味着增量之间的差异必须为1(因为它是唯一与所有其他正整数相互作用的正整数)。

对于(1,3),差异为3-1=2,周期长度为222不是互质,因此算法不是保证找到循环。

理解这一点的关键是,至少为了检查指针是否满足,慢速和快速指针'周期内的位置仅相互关联。也就是说,这两者可以被认为是等价的:(两者的差异为1)

slow fast             slow fast
   ↓ ↓                   ↓ ↓
 0→1→2→3→4→5→0     0→1→2→3→4→5→0

因此,我们可以根据slow保持不变的位置和fastfastIncrement-slowIncrement的增量移动的位置来考虑这一问题,此时问题就变成了:

  

从任何位置开始,我们能够以某个速度(模式周期长度)到达特定位置吗?

或者,更一般地说:

  

我们能否以某种速度(模式周期长度)到达每个位置?

只有在速度和周期长度是互质的情况下才会出现这种情况。

例如,查看速度为4和长度为6的循环 - 从0开始,我们访问:
0, 4, 8%6=2, 6%6=0, 4, 2, 0, ... - GCD(4,6)= 2,我们只能访问每一个元素 要看到这一点,请考虑上面给出的示例的(1,5)(差值= 4)的增量,并看到指针永远不会满足。

我应该注意到,据我所知,(1,2)增量被认为是算法的基本部分。

使用不同的增量(根据上述约束)可能会有效,但这将是一个远离官方"算法并且涉及更多的工作(因为指向链表的指针必须迭代递增,你不能在一个步骤中将它递增超过1),而对于一般情况没有任何明显的优势。

答案 1 :(得分:0)

伯恩哈德·巴克 (Bernhard Barker) 的解释很到位。 我只是在添加它。

为什么指针之间的速度差和循环长度应该是 互质数?

假设指针(例如 v)和循环长度(例如 L)之间的速度差异不是互质的。 所以存在一个大于 1 的 GCD(v,L)(比如 G)。

因此,我们有

  • v=指针之间的速度差
  • L=循环的长度(即循环中的节点数)
  • G=GCD(v,L)

由于我们只考虑相对位置,因此本质上 slow 是静止的,而 fast 以相对速度 v 移动。 让 fast 位于循环中的某个节点。

由于 GL 的除数,我们可以将循环划分为总帐部分。从 fast 所在的位置开始划分。

现在,vG 的倍数(比如 v=nG)。 每次 fast 指针移动时,它都会跳过 n 部分。所以在每个部分,指针到达一个节点(基本上是一个部分的最后一个节点)。每次fast 指针都会落在每个部分的结束节点。参考下图

Example image

正如上面伯恩哈德所说,我们需要回答的问题是 我们可以到达以某种速度移动的每个位置吗?

如果我们有现有的 GCD,答案是。正如我们所见,fast 指针只会覆盖每一部分的最后一个节点。