链表循环 - 循环开始元素和列表长度

时间:2012-09-06 11:19:24

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

我读到loop in linked list detection algorithm 我怀疑

1)如何检测“会议元素”。例如,在以下情况中 - 如何检测会议是否位于第3个元素?

enter image description here

2)如何检测列表的长度(如果超过 - 6)

运行时间O(n),内存O(1)中的两个问题。

3 个答案:

答案 0 :(得分:9)

使用tortoise-hare算法(floyd的循环检测),我们可以在给定的列表中找到循环。

即如果我们移动两个指针,一个速度为1而另一个速度为2,如果链表有一个循环,它们将会结束。为什么?想想两辆在赛道上行驶的汽车 - 速度越快的汽车总会越过慢速行驶!

这里棘手的部分是找到循环的开始。想象一下,作为一个类比,两个人在赛道上比赛,一个赛跑的速度是另一个赛车的两倍。如果他们在同一个地方开始,他们下一次会什么时候见面?接下来他们将在下一圈开始时见面。

因此,在确定循环后,如果我们将n1移回Head并在MeetingPoint保持n2,并以相同的速度移动它们,它们将在LoopStart(会议元素)处相遇。 < / p>

然后,为了找到长度,当将n1移回头部时定义一个长度变量。现在在每次移动时增加长度变量。在确定LoopStart之后,保持n1 ptr,并为每次移动移动n2 ptr和inc长度。 当n2-&gt; next == n1时,返回长度

这将有运行时间O(N),空间复杂度O(1)

答案 1 :(得分:0)

当使用Floyd的循环寻找算法时,快速和慢速参考将不会在第三个元素处满足,而是在第四个元素处。他们的位置从(1,2)开始,并且如下所示:(1,2) - &gt; (2,4) - &gt; (3,6) - &gt; (4,4)。

我认为,为了找出周期的确切位置,你需要O(n)空间以及O(n)时间。

答案 2 :(得分:0)

我认为你不能仅使用O(1)工作记忆在O( n )时间内做到这一点。

“会议元素”(周期开始)有 n 不同的候选者,而在O(1)存储器中,您只能记录固定数量的它们。如果您可以多次遍历该结构,那么这不一定是个问题,但是如果您只能在每次遍历中检查固定数量的节点,则需要遍历结构 n 次, O( n ²)总时间。

直接的解决方案是放弃O(1)内存要求。绕过循环一次并将指针存储到散列表中的节点,直到找到重复的条目。预期时间O( n ),内存使用量O( n )。