Floyd's Cycle Detection
Floyd’s Cycle Detection
使用情境
- 当有节点发生
迴圈
的状况,可以用Floyd's Cycle Detection
检测迴圈的点在哪
判断串列(Link List)是否有迴圈 cycle
- 产生
2 个指针
指向同一个起点,一个指针为slowPointer 慢指针
、一个指针为fastPointer 快指针
fastPointer 快指针
移动的速度是slowPointer 慢指针
的2 倍速
- 如果 2 个指针,移动到最后的节点,没有相遇,表示此串列没有
迴圈 cycle
- 如果 2 个指针,移动到某个节点相遇了,表示
fastPointer 快指针
从后面追上了slowPointer 慢指针
,那表示这个串列有迴圈 cycle
判断发生迴圈的点在哪
- 当 2 个指针第一次相遇后,将其中一个指针设定为之前的起点,假设为指针
resetPointer
,其中一个指针留在原本的迴圈中,假设叫做指针cyclePointer
- 然后 2 个指针都变回
慢指针
,都一次只移动 1 步 - 当两个指针再次相遇,那个点就是导致
迴圈 cycle
的点 - 而在导致
迴圈 cycle
的点,维持原本resetPointer
不动,cyclePointer
自行移动,最后再次与resetPointer
相遇,那移动的步数,就是整个迴圈的长度
程式
TypeScript
function findDuplicate(numsList: number[]): number {
// Floyd's Cycle Detection
// 慢指针
let slowPointer = 0;
// 快指针,移动速度是「慢指针」的 2 倍
let fastPointer = 0;
while (true) {
// 移动慢指针
slowPointer = numsList[slowPointer];
// 移动快指针
fastPointer = numsList[numsList[fastPointer]];
if (slowPointer == fastPointer) {
// 「慢指针」与「快指针」相遇
break;
}
}
// 重设新的指针,与在迴圈中的慢指针比较
let slowPointer2 = 0;
while (true) {
// 移动两指针用同样的速度
slowPointer = numsList[slowPointer];
slowPointer2 = numsList[slowPointer2];
if (slowPointer == slowPointer2) {
// 两指针相遇,相遇的点就是迴圈发生的点
break;
}
}
// 迴圈发生的点就是重複的数字
return slowPointer;
};
参考资料
- Find the Duplicate Number - Floyd’s Cycle Detection - Leetcode 287 - Python - YouTube
- Floyd’s cycle detection algorithm (Tortoise and hare) - Inside code - YouTube
- 菜鸟工程师 肉猪: Floyd Cycle Detection Algorithm 龟兔赛跑算法
- If Programming Was An Anime - YouTube
- Floyd判圈算法 - 维基百科,自由的百科全书