Floyd的cycle-detection算法解析(原创)
要解决的问题是:
如何确定一个链表中时候存在环,如果存在的话,环的起点在哪里?
Floyd 的算法又叫做龟兔赛跑算法,那么我们就用龟兔赛跑来解释。
我们假设乌龟和兔子的速度是1:2,然后假设乌龟的兔子在赛道的某一点相遇了。(相当于他们直线跑入一个环形赛道,然后在赛道的某一点相遇了)那么因为他们跑得时间是一样的,即他们跑得路程1个是i,另一个是2i。借用上图的表示,我们有如下等式:
1) i = m + p*n + k
2) 2i = m + q*n + k
这里的p和q分别是兔子和乌龟在环里跑得圈数。q>p
解上面的等式去掉i,我们就得到下面这个重要的等式:
m + k = (q-2p) * n (等式一)
因此,如果我们能够证明至少有一种k, p, q的值可以使得这个等式成立,我们就证明了这样的m和n的是存在的。(如果环存在,即上面等式成立,m和n的值是确定不可变的,只有k,p,q是可变值。) 进而也就证明了乌龟和兔子的相遇是成立的。
这里我们只要使 k = m*n-m; q-2p = 2m; 也就是说存在k,q,p的确定的值的组合(因为他们都可以用m和n表示),使得上式成立。
下面我们来解决第二个问题,即环的起点在哪里。
让我们再加一只乌龟进来,叫做乌龟二号。 乌龟二号和乌龟一号有同样的速度。当乌龟二号在链表起点时,乌龟一号和兔子相遇在环内的K处。
现在,当两只乌龟一起走m步时,即乌龟二号到达了环的起点,这时候
乌龟一号走的总路程 = m + p*n + k + m
根据等式一计算m+k得出:
乌龟一号走的总路程 = (q-2p) * n + p*n + m
即
乌龟一号走的总路程 = (q-p)*n + m
所以当乌龟二号在环起点的时候,乌龟一号走过了(q-n)圈个环,再加上m的路。所以乌龟一和乌龟二第一次相遇的时候的点就是环的起点。
参考http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare
如何确定一个链表中时候存在环,如果存在的话,环的起点在哪里?
借用这张经典的解析图
Floyd 的算法又叫做龟兔赛跑算法,那么我们就用龟兔赛跑来解释。
我们假设乌龟和兔子的速度是1:2,然后假设乌龟的兔子在赛道的某一点相遇了。(相当于他们直线跑入一个环形赛道,然后在赛道的某一点相遇了)那么因为他们跑得时间是一样的,即他们跑得路程1个是i,另一个是2i。借用上图的表示,我们有如下等式:
1) i = m + p*n + k
2) 2i = m + q*n + k
这里的p和q分别是兔子和乌龟在环里跑得圈数。q>p
解上面的等式去掉i,我们就得到下面这个重要的等式:
m + k = (q-2p) * n (等式一)
因此,如果我们能够证明至少有一种k, p, q的值可以使得这个等式成立,我们就证明了这样的m和n的是存在的。(如果环存在,即上面等式成立,m和n的值是确定不可变的,只有k,p,q是可变值。) 进而也就证明了乌龟和兔子的相遇是成立的。
这里我们只要使 k = m*n-m; q-2p = 2m; 也就是说存在k,q,p的确定的值的组合(因为他们都可以用m和n表示),使得上式成立。
下面我们来解决第二个问题,即环的起点在哪里。
让我们再加一只乌龟进来,叫做乌龟二号。 乌龟二号和乌龟一号有同样的速度。当乌龟二号在链表起点时,乌龟一号和兔子相遇在环内的K处。
现在,当两只乌龟一起走m步时,即乌龟二号到达了环的起点,这时候
乌龟一号走的总路程 = m + p*n + k + m
根据等式一计算m+k得出:
乌龟一号走的总路程 = (q-2p) * n + p*n + m
即
乌龟一号走的总路程 = (q-p)*n + m
所以当乌龟二号在环起点的时候,乌龟一号走过了(q-n)圈个环,再加上m的路。所以乌龟一和乌龟二第一次相遇的时候的点就是环的起点。
参考http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare
评论
发表评论