在链表中查找循环的起始节点?

时间:2012-07-21 10:24:39

标签: algorithm data-structures linked-list

如何在给定的链表中找到循环的起始节点?我们称之为循环点

到目前为止,我已经理解了以下内容(使用慢速/快速指针):

  1. 假设列表具有大小为k
  2. 的非循环部分
  3. 慢动作k步
  4. 快速移动2k步
  5. 快速是(2k - k)= k步骤ahead
  6. 慢是在循环的开始;也称为Cycle point
  7. 来自(LOOP_LENGTH - k)的{​​{1}}步behind或此时指针缓慢
  8. 每1步慢动作,快速移动2步,慢速增加1步。
  9. 因此,需要快速Cycle point步骤才能遇到慢和碰撞
  10. 这是我不明白的一步: 在此碰撞点,两个节点将从循环前方(LOOP_LENGTH - k)步进。
  11. 找到碰撞点后,将一个指针移动到列表头部。
  12. 现在以1步/转的速度移动两个指针直到碰撞。它们都遇到的节点是循环的开始,因此是k
  13. 有人可以在第9步之后向我解释一下吗?

    由于

    修改

    我想指出的一点是,一旦进入循环,快速将永远不会超过慢指针。他们会发生碰撞。这就是原因:慢速在i,快速在i-1处假设。当他们移动时,slow => i + 1和fast也将在i + 1,因此碰撞。或者,慢速在i,快速在i-2。下一步,慢 - > I + 1;快:我下一步,慢 - > i + 2,快速:i + 2,因此再次碰撞。如此之快将永远无法超越缓慢,只会在循环中碰撞一次!

2 个答案:

答案 0 :(得分:3)

你的6.错了,快指针离那个时间周期点的慢指针还有k步;但最好使用 提前 支持 ,而不是远离。另外,k可能更小,更大或等于loop_length

因此,当指针达到循环点时,快速指针在k之前超前一步,在开始之后,这是k步。现在,在循环上测量,快速指针在循环点之前步进k % loop_length。对?如果k = some_n * loop_length + r,则快速指针在循环点之前步进r,也就是说,r := k % loop_length前进。

但这意味着慢速指针在循环中的loop_length - r步骤 在快速 之前。毕竟这是一个循环。因此,在loop_length - r个额外步骤之后,快速指针将捕获到慢速指针。对于每一步,慢指针移开,快速移动靠近两个步。

因此我们不知道k,我们不知道loop_lengthr,我们只知道m = k + loop_length - r = some_n * loop_length + r + loop_length - r = (some_n+1) * loop_length。直到两个指针会合点的步骤m的总数是循环长度的倍数。

所以现在我们重新开始,在开始时有一个新指针,在新的指针前面遇到快速m步骤。我们以相同的速度移动新的和慢的,每次移动1步,并且在它们应该满足的循环点 - 因为当新指针到达循环点时,第二步仍然是m步,也就是说,m % loop_length == 0沿循环前进。这样我们就可以找出k是什么(我们一直在计算我们的步数)和循环点。

我们再次沿着循环找到loop_length,直到两人再次相遇。

答案 1 :(得分:0)

嗯..这种问题很难解释,除非你是面对面交谈。我试试看。

首先在第6步中:我认为快速指针距离圆点的距离应该k

但是留下这一切。我们现在有两辆车。一辆快车的速度是慢车速度的两倍。

假设快速车在距离圆点k距离的圆形轨道上开始。

慢车从圆点开始。

现在我说两辆车都会在圆点前k距离见面。

为什么呢?因为最初快车距离圆点k距离。第一次完成圆圈时,快速车将覆盖n距离。现在,快车再次与圆点相距k距离。但是慢车距离圆点n/2距离。

现在,快车必须覆盖n-2k距离,以便在圆点之前达到k距离。慢车必须覆盖n/2 - k = (n-2k) / 2距离,才能在起点前达到k距离。 Which is exactly half the distance of the path to be covered by the fast car。快车的速度是慢车的两倍。

很明显,他们会在圆点前k距离见面。