我不确定如何在不使用O(N)内存和标志
的情况下找到循环的开始答案 0 :(得分:6)
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)
遍历,当你点击已经访问过的节点时,这就是周期回归的地方。