这个问题与查找2个链接列表的交集有点不同。
考虑带有循环的链表:A - B - C - D - E - F - C
。
如果节点A
是函数的输入,那么它应该返回C
。
由于我不知道要调用C
的内容,我使用了一个术语循环节点C
,如问题中所示。虽然O(n 2 )术语显而易见,但是有没有办法找到复杂度较低的循环节点?
不允许使用O(n)的哈希表/额外空格。
答案 0 :(得分:5)
使用两个指针有一个简单的方法。第一个指针以慢速指针的速度增加一倍和第二个。
你的情况所以链表实际上是A-&GT; B-&GT; C-&GT; D-&GT; E-&GT; F-&以及c含义f再次回指向C.So方法是象下面< / p>
1.保持增加两个指针直到它们匹配。所以在上面的情况下我们会有这些步骤
慢指针:A B C D E
快速指针:A C E C E
所以我们停在E处,这表示有一个循环。现在我们需要找到循环节点。
现在从E移动指向链表开始的慢速指针并创建一个指向E的新指针,并且还增加1.这两个指针相遇的点实际上是循环节点。所以在我们的例子中
从头开始的指针:A B C新指针:E F C
因此,当您看到他们在C会面时,我们已经完成了在链接列表中查找循环节点。
<强>更新强> 对于这种方法的数学证明,请参考这个精彩的问题,并看到@Jim Lewis回答所有答案下面的评论。 Explain how finding cycle start node in cycle linked list work?
答案 1 :(得分:0)
Floyd's cycle-finding algorithm是最简单的,通常是“规范的答案”,因为这是每个人在大学里学到的东西(也许是因为它简单,优雅,富有洞察力)。
经常声称运行时不是可以改进的,但事实并非如此 - 大哦可能不会改进,但这只能告诉我们最坏情况下的渐近行为。 Brent's algorithm在练习中速度更快,同时仍然使用恒定的空间。有更多算法,例如Gosper的Loop Detection或Sedgewick,Szymanski和Yao的算法或k-stacks algorithm,它们都使用一定的(理论上低但非常数)空间量。实际上,对于链表的任何实际实现,空间量仍然是恒定的,因为你的指针将是固定大小的。例如,使用32位指针,Gosper的循环检测将使用33个字的空格(可能还有一些额外的,取决于您想要计算的内容)。
Floyd的算法很好,但不一定是答案(tm)。有选择和权衡取舍。