Floyd判圈算法(Floyd Cycle Detection Algorithm),又称龟兔赛跑算法(Tortoise and Hare Algorithm),是一个可以在有限状态机、迭代函数或者链表上判断是否存在环,以及判断环的起点与长度的算法。
其算法的思想如下:
如果有环=》
- 有限时间内快慢指针必然相遇且相遇点在环上
- 相遇点和起点的等速指针将在环的入口处相遇
其算法的用处如下:
- 判断是否有环
- 找到环的起点
- 计算环的长度
1,判断是否有环=》
这个非常简单。设计一个快指针,一个慢指针,同时从起点出发,有限时间后 快慢指针能相遇即代表有环,永远不相遇代表没环。道理很简单,好比龟兔在操场上的环形跑道上赛跑,同时从起点出发,兔子比乌龟速度快,两者匀速,那么有限的时间后兔子一定能追上跑得慢的乌龟,再次相遇时,且兔子领先乌龟刚好一圈。但如果是在线性路上赛跑,兔子将持续领先,中途永远也不会相遇,直到兔子到达终点停下来。
如下图,用快慢指针简单模拟一下龟兔赛跑。从起点出发,兔子一次跑两步,乌龟一次跑一步。
2,找到环的起点=》
我们发现,龟兔确实相遇了,而且是在环上。那么问题来了,如何判断环的起点呢?其实这就是Floyd判圈算法(Floyd Cycle Detection Algorithm)的最巧妙之处了。
首先回顾一下Floyd判圈算法思想:
如果有环=》
1. 有限时间内快慢指针必然相遇且相遇点在环上
2. 相遇点和起点的等速指针将在环的入口处相遇:
接下来我们将逐句深刻理解并用严谨的逻辑证明这个命题的正确性
逻辑证明
首先,“1.有限时间内快慢指针必然相遇且相遇点在环上”可以转换成以下两个命题
1.1有限时间内两个指针都能运动到环上
1.2快慢指针在环上时,在有限时间内必然能相遇
这两个命题很好理解,不多做解释。
只简单说以下。
由于是单向的,有限时间后肯定能运动到环上,1.1正确。
1.1成立=》运动到环上后,那有限时间内快的必然追到慢的,即必然能相遇,就和前面说的操场环形跑道一样。1.2正确
然后,“2.相遇点和起点的等速指针将在环的入口处相遇"同样可以转换成以下两个命题
2.1相遇点和起点的等速指针将在环上相遇
2.2在环上相遇的等速指针必定在环的入口处首次相遇
2.1相遇点和起点的等速指针将在环上相遇
由命题1已经确定,快慢指针一定会相遇在环上。相遇时,记慢指针走过了n的距离,那么快指针走过了2n的距离,即单位时间内快指针能比慢指针多走一个n。
这个时候让慢指针回到起点,快指针还在相遇点。即让快指针先走n的距离。但此后两个指针的前进速度相同,区分为前指针和后指针。
单位时间后,后指针走了n的距离,前指针也走了n的距离。但由于前指针起点是n,所以相当于走了2n。那么这和第一次快慢指针情况一样,那么说明前后指针至少会在刚才的相遇点相遇(也可能其实早在这个点之前就已经相遇了,如图演示,在首次的相遇点D之前,其实就已经在C相遇了)
2.2在环上相遇的等速指针必定在环的入口处首次相遇
等速指针只要相遇了,那么此后时时刻刻都将相遇,那么首次相遇的上一次一定是非环上,那么首次相遇的地方就是在环的入口。
3,计算环的长度=》
两种办法,
一,快慢指针相遇后,继续执行并重新对快慢指针进行计步,直到快慢指针第二次相遇,此时快指针比慢指针多走的距离就是环的长度。
二,在找到环的入口后,一步一步遍历回到起点时,走过的距离就是环的长度。