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判圈算法 - 维基百科,自由的百科全书