为什么会议在循环中指向与链表开头相同的步骤数?

时间:2018-05-29 21:30:02

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

有一个明显标准的方法来查找链表是否有一个循环,然后返回循环开始时的节点,该节点是floy的慢速/快速指针算法。
除了一件事,代码和逻辑是清楚的 该方法基于以下假设:指针将满足的循环中的节点与从列表头部到循环开始的步骤数完全相同。 那部分是我没有得到的。
因此,如果慢速和快速都从列表的头部开始,当慢速执行k步并到达循环的开始时,快速将完成2k步并且实际上是进入循环的步骤。
如此快速前进缓慢的k步和慢速(在循环开始时)N - k,其中N是循环大小。
由于在每个步骤中快速接近慢速且快速慢慢地落后于N-k个节点,因此快速将在N-k步骤中达到缓慢 此时,慢速将完成N - k步并将在节点N - k中 快速将完成2(N - k)步并且将在节点2N - 2k + k = 2N - k(因为快速在节点k处)。
由于这是一个循环2N-k = N-k,因此它们在节点N-k处相遇 但是为什么N-k节点k从循环开始步进? 我在这里误解了什么?

2 个答案:

答案 0 :(得分:0)

这是你缺少的。

每当两个指针都在循环中并且快速指针是前面循环长度的倍数时,快速指针已经缓慢整数倍并且它们位于相同的位置。如果你继续他们将分开并将再次圈。然后再次。再一次。

算法工作的全部原因是这种研磨行为。

他们第一次见面时,可能是周期长度的严格倍数。例如,如果你有一个24个节点的链节进入一个长度为7的循环,那么它们将在28个步骤之后首先相遇。

修改 我在解释循环检测是如何工作的,而不是如何检测磁头的工作原理。这是对此的另一种解释。换句话说。

假设我们有一个i个节点链,这些节点导致一个长度为j的循环。我们最初运行快速+慢速指针,他们见面了。为了满足,快速必须在循环周围比慢速更多整数倍。所以他们在k*j步之后见面。

此时,慢速指针总共行进了k*j个步骤,其中i个步骤进入循环,因此它已经在循环内行进了k*j-i个步骤。

现在我们将快速指针放在开头,然后以相同的速率前进。在另一个i步骤中,开始处的指针已到达循环。与此同时,缓慢的指针先前已经在循环内部行进了k*j-i个步骤,现在又在循环内的i步进了k*j个步骤。由于k*j是循环长度的倍数,因此它也会在开始时返回并再次相遇。

答案 1 :(得分:0)

让我为您提供另一种解决此问题的方法,最后,您也可能会得到答案。

用于解释的变量:

  • N-链表中节点链接的总数。
  • C-从头到循环起点的距离
  • Y-从循环开始到会合点的距离。
  • K-从集合点到循环起点的距离。

因此,我们可以从这些变量得出一些结论。

  1. N = C + Y + K
  2. 慢速指针覆盖的距离-Ds = C + Y
  3. 快速指针覆盖的距离-Df = N + Y

For representation

在这里,

  • N = 12
  • C = 2
  • 两个指针都将在节点编号11处相遇,因此Y = 8
  • K = 2

由于我们知道快指针比慢指针快2倍,所以 Df = 2 * Ds

利用Df和Ds之间的关系,并从上方放置值

N + Y = 2 * ( C + Y )

N + Y = 2*C + 2*Y

N = 2*C + Y

使用N的另一个关系,

C + Y + K = 2*C + Y

K = C

结论是,头部与循环起点之间的距离等于交汇点节点与循环起点之间的距离。

尝试理解这一点,并始终尝试通过将其分成较小的块来简化任务。

希望这会有所帮助。

继续提问,保持成长:)