如何使用循环查找链表的循环节点?

时间:2013-08-25 03:04:19

标签: java algorithm data-structures linked-list singly-linked-list

这个问题与查找2个链接列表的交集有点不同。

考虑带有循环的链表:A - B - C - D - E - F - C

如果节点A是函数的输入,那么它应该返回C

由于我不知道要调用C的内容,我使用了一个术语循环节点C,如问题中所示。虽然O(n 2 )术语显而易见,但是有没有办法找到复杂度较低的循环节点?

不允许使用O(n)的哈希表/额外空格。

2 个答案:

答案 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)。有选择和权衡取舍。