如何删除单个链表中的循环?

时间:2009-08-16 22:55:39

标签: algorithm

我不确定如何在不使用O(N)内存和标志

的情况下找到循环的开始

5 个答案:

答案 0 :(得分:6)

  • 在循环内查找节点(有关详细信息,请参阅1800 INFORMATION的答案)。我们称这个节点为C
  • 通过从C推进指针直到它再次到达C来查找循环的长度。循环的长度是它所采取的步骤数。我们称这个长度为L
  • 创建一个从起点向前迈步L的指针,以及指向起点的另一个指针。现在一步一步推进他们,直到他们相遇。这将是循环的切入点。

O(N)时间,O(1)记忆。

不过,你需要这个吗?

答案 1 :(得分:3)

有一个非常好的算法,它使用常量空间,O(n)运行时和只有两个指针。您使用第一个指针从头部遍历列表,并使用第二个指针以双倍速度遍历列表。在每一步比较指针,如果它们相等,你就找到了循环。

答案 2 :(得分:2)

维护一个到目前为止访问过的节点列表,并在每个节点到达时将每个节点与列表进行比较(速度慢,但不需要基础设施),或者对每个节点“着色”,并检查下一个节点是否“着色”已经(要求你在每个节点中安装一个“颜色”标志)。

或使用1800 INFORMATIONS's suggestion在循环中获取 节点。使用它来查找循环的完整列表,然后再次转回完整列表(与循环列表比较),在循环中找到第一个节点。

答案 3 :(得分:1)

我认为yairchu使用1800的find方法的答案是最好的解决方案 - 其中一个让我微笑的解决方案; - )

但是我会继续发布我正在考虑的内容,它只使用了4个额外的指针和一个布尔值。

让我们将节点称为a-> b-> c-> ...

如果你从a开始并通过列表以相反的方式翻转指针(需要两个额外的指针来帮助解决这个问题)并且一直到达不是a的结束,你当然没有环。呜啊!你可以回来重新翻转指针,你已经完成了。

但是如果你有一个循环,会发生什么事情你会一直回到a,并且指针会留下这样的,下一次反复出现,你会在相反的情况下遍历循环方向。 (您可以在每次旅行中切换布尔值,以便知道循环是否处于原始顺序。)

因此,在第一次出入和退出时,您指向a作为正在测试的节点并将b记录为它指向的内容。下一次,如果你发现a不再指向b,则a是循环中的第一个节点。否则,在同一行程中,您将转移到b作为正在测试的节点并记录它指向的内容等,直到找到循环的开始。使用布尔值,您可以知道在打破循环时哪种方式离开指针。

不幸的是,

O(n ^ 2)时间,但无论如何它都会使记忆保持不变。

答案 4 :(得分:-1)

遍历,当你点击已经访问过的节点时,这就是周期回归的地方。