1.概述

在本教程中,我们将学习如何在链接名单。此外,我们还将分析每种方法的不同时间和空间复杂性。此外,我们将研究最有效的算法并证明它。此外,我们将证明它的线性时间复杂度。我们假设对链表数据结构和大0符号

2.问题陈述

假设我们有一个单独的名单。此列表有一个循环。因此,我们的任务是返回一个循环启动节点。我们唯一给出的是链接列表头(启动节点)。让我们来看看一个更好的理解的例子:

这里,起始节点是1。但是,在节点4之后,我们进入了一个循环4 - 5 - 6 - 7 - 8 - 9 - 4。然后,在从节点9到达下一个节点之后,我们将再次开始这个循环。此外,我们永远不会到达链表的结尾,因为它不存在。我们的目标是返回节点4作为循环的开始节点。

野兔和乌龟

有几种算法可以帮助我们解决这个问题。例如,我们可以用ahashset.。在每个步骤中,我们将检查我们集中的当前节点是否存在。如果它确实,那么它将是循环的起始节点。如果没有,那么我们要将此节点添加到并移动到下一个节点。这种解决方案的时间复杂性是上)。但是,空间复杂性也是如此上)

还有另一种解决方案,它使用上)时间。但是,它使用恒定的记忆,我们可以减少空间复杂性O(1)这是弗洛伊德的野兔和乌龟算法。这是一个指针算法,它使用一个快速指针和一个缓慢指针来寻找循环开始节点

3.1。算法的想法

假设我们有两个指针。一个指针比另一个快两倍。较慢的指针被称为乌龟,因为这种爬行动物的缓慢是众所周知的。另一方面,更快的指针被称为野兔。在我们的图表中,乌龟用绿色表示,兔子用红色表示:

在一开始,它们位于列表的起始节点1。乌龟一次将移动一个节点。相反,野兔将移动两次,跳过一个节点。4移动后,野兔处于节点9.然而,乌龟刚刚达到节点4。

重要的是要注意,他们都无限地开始循环。该列表包含一个周期,它们都输入此循环。结果,他们肯定会在某个时候见面。但是,我们在遇到之前的时间段感兴趣。这会影响算法的时间复杂性。此外,我们将证明他们最多会见面k步骤,其中k是循环的长度。它还意味着,野兔甚至不会在第一次会议之前完成整个周期。

3.2。解释

算法的第一部分很简单,我们的动物将开始移动,直到它们相遇。这是野兔和乌龟各自的轨迹:

如果他们同时移动,它们会在制作6步后在节点7的周期中见面:

算法的第二部分也很简单。我们把兔子移到起始位置,并减慢速度两次。所以,现在它的速度与乌龟相同。乌龟继续从现在的位置移动。接下来,他们再次开始移动,直到他们再次见面。有趣的事实:它们会在循环入口相遇,这就是问题的答案。之后,我们返回此节点并完成算法。

我们将在下一节中证明它们将在循环开始的节点处再次相遇。现在,让我们把兔子放在名单的开头,看看它们会在哪里和乌龟相遇:

正如我们所看到的,我们的动物在节点4遇到,这正是循环的开始。

4.Floyd算法的证明

这个证明比算法要难一点,但它在直觉上是清楚的。我们将把证明分为三部分。

4.1。第一次见面

首先,让我们展示一下他们会在搬家后相遇。显然,它们会在一个循环中相遇。假设这个循环的长度是k。当乌龟将进入周期,头发将已经在周期的位置x。现在,我们可以去另一个坐标系。我们将把兔子和乌龟的速度降低1。现在乌龟不会移动,兔子将以每1单位时间1个节点的速度移动。有K  -  X.它们之间的节点。兔子快要够到乌龟了K  -  X.步骤。

让我们考虑他们的真实速度雷竞技app官网网站。野兔比乌龟移动两倍。因此,它意味着,上述速度变换模拟相同的情况。

4.2。直观的解释

现在我们在这个位置找到了他们的第一个会合点x。根据算法,我们必须降低兔子的速度,并将其移动到列表的开始。当它们再次相遇时,相遇点就是循环开始节点。

假设米为从开始节点开始的列表的长度s_ {0}到循环入口年代。我们也l是周期的长度。兔子和乌龟在结点上相遇x在循环。让Y距离年代x。,让Z距离x年代:

进一步,我们将证明M = a \乘以L + Z。这将有助于我们现在解释为什么我们的指针会在周期开始时满足。

我们会议后转移野兔x在它们开始同时移动之前。乌龟将会一个循环并出现在x再次。它必须制作Z达到循环开始的步骤。重要的是要记住,我们把兔子的速度降低到等于乌龟的速度。这样,兔子就会成功L \倍s_ {0}然后会有Z左转到循环开始的步骤年代,与乌龟一样。但是,它只有当且仅当当起作用m = a \ times l + z,在那里一个是一个常数值

4.3。正式的证明

我们将证明这一点M \mod L = Z,在那里\国防部是个模操作它只是表示我们可以除米通过l而且分裂后的其余部分将是Z.这将有助于证明动物将再次见面年代。如果M \mod L = Z然后,我们能够再现动物的运动,在先前的子部分中提到。想象一下,距离m可能很长。通过证明M \mod L = Z,我们会展示这一点M = a \乘以L + Z

在动物们第一次相遇之前,兔子的距离就会变远h_ {1} = m + a \ times l + y一个是一个常数值。如果米很长,然后兔子会在一个循环中做许多圈等待乌龟。与此同时,乌龟距离是T_{1} = m + y。如果乌龟比野兔慢两次,我们可以弥补平等:

2 \乘以T_{1} = H_{1},或2 * (M + Y) = M + L + Y。它等于M + Y = a * L。记住这一点很重要吗Y = l - z

因此,M + L - Z = a * L,或m =(a  -  1)* l + z

采取\ mod l.在我们得到的平等的两边M \mod L= ((a - 1) * L + Z) \mod L= (a - 1) * L \mod L + Z \mod L = 0 + Z \mod L = Z \mod L

最后,我们证明了它M \mod L = Z。这意味着弗洛伊德的算法有效。

5.时间和记忆复杂性

我们可以注意到,我们使用恒定的空间复杂性这只是两只指针:兔子和乌龟。

算法的时间复杂度为上),在那里n是列表中的节点数。时间复杂度是线性的,以防我们赚的不超过n + k在他们第一次见面之前,用我们的指针进行步骤。k是循环的长度和k \ leq n。因此,第一部分采取上)时间。算法的第二部分也会上)步骤。因此,最终的时间复杂度为O(n)+ O(n)= o(n)

6.结论

在本文中,我们讨论了在链表中寻找循环开始节点的方法。并对解决该问题的最有效算法进行了说明和证明。此外,我们已经给出了证明的直观解释。两指针方法是一种流行的技术,它可以用于许多算法问题。例如,同样的兔子和乌龟可能帮助我们找到数组中重复的数字

评论在本文上关闭!