图解Floyd判圈算法 | 判断链表或者迭代函数是否有环 | Java代码
1.Floyd判圈算法概述🍇
🍑定义:
Floyd
判圈算法(Floyd Cycle Detection Algorithm
),又称龟兔赛跑算法(Tortoise and Hare Algorithm
),是一个可以在有限状态机、迭代函数或者链表上判断是否存在环,以及判断环的起点与长度的算法🍏🍒算法思想:
- 有限时间内快慢指针必然相遇且在相遇点在环上1️⃣
- 相遇点和起点的等速指针将在换的入口出相遇2️⃣
🍓算法作用:
- 判断迭代函数或者链表上面是否有环1️⃣
- 如果有环可以找到环的起点2️⃣
- 如果有换可以计算环的长度3️⃣
🫐这个算法只需要大家了解其原理就行,毛毛张在这里不做严密的逻辑推导,而是通过推介举例的方式来帮助大家理解这个算法
2.如何判断是否有环🍉
- 由于这个算法的另外一个名称是龟兔赛跑算法,因此毛毛张就拿龟兔赛跑的例子来举例说明:
- 假设:我们可以假设有乌龟和兔子在一个跑道上比赛跑步,我们默认兔子的跑步速度是快于乌龟的
- 如果是直线型跑道,两者同时从起点出出发,中途乌龟是永远追不上兔子的,直到涂子到达终点
- 如果是环形跑道,两者同时从起点出发,经过有限的时间内,兔子会追上乌龟,两者相遇,如果运动过程中兔子的速度是乌龟速度的两倍,那么两者第一次相遇时,兔子的路程就是乌龟路程的两倍
- 上面这个例子是小学问题中一个很简单的相遇和追及问题,我们回到这个算法本身:
- 假设兔子就是那个快指针
fast
,每次走两步,乌龟就是那个慢指针slow
,每次走一步 - 如果链表或者迭代函数没用环,那么快指针迭代到终点,在此过程中,两个指针是不会相遇
- 如果链表或者迭代函数有环,那么快指针在迭代过程中一定会追上慢指针
- 假设兔子就是那个快指针
- 图解:
3.如何找到环的起点🍍
在上面的问题中,我们假设快指针的速度是慢指针的两倍,那么在相同时间内,第一次相遇的时候,快指针走过的距离为2n,慢指针走过的距离为n,因此单位时间内快指针比慢指针多走一个$n$;于是我们让慢指针回到起点,快指针还在相遇点,即让快指针先走$n$的距离;然后让两个指针的前进速度相同,区分为前指针和后指针
图解:
4.计算环的长度🥭
- 顺着找到环的入口的思路,我们可以得到方式1:在找到环的入口后,一步一步遍历回到起点时,走过的距离就是环的长度
- 顺着判断是否有环的思路,我们可以得到方式2: 在找到相遇点之后,继续执行并重新对快慢指针进行计步,直到快慢指针第二次相遇,此时快指针比慢指针多走的距离就是环的长度
- 方式3: 当快慢指针相遇之后,让快指针一步一步遍历回到相遇点时,走过的距离就是环的长度
5.代码实现🍎
1 | class ListNode { |
参考文献
-------------本文结束感谢您的阅读-------------