【解題筆記 - JS】Node 找到循環鍊的長度

更新 發佈閱讀 6 分鐘

Node 對我來說一直是很似懂非懂的概念,題型有樹狀、鏈節等。因為沒有實際可見的數字或字串等實物可以觀察中間步驟,所以比起其他解題抽象許多。如果光是查找 Node 各型定義還是不好理解,要怎麼使用這些知識連結解題方法。所以我認為有圖解步驟輔助,會是比較容易理解的步驟。

以下解題方法來自網友與 GPT 提供的答案,我想在本文中嘗試自己做視覺化圖解,說明 CodeWars 5kyu - Can you get the loop ? 的解題思路。


題目資訊

  • 題目來源:https://www.codewars.com/kata/52a89c2ea8ddc5547a000863
  • 題目說明:
    給您一個作為鍊錶開頭的節點。此清單包含一個懸掛塊和一個循環。您的目標是確定循環的長度。您可以使用 node.getNext()node.next 這兩個方法走入下一個節點。
    ※ 環長就是下圖中紫色的區塊


先前我一直很糾結於上圖,以為一定要找到環與鏈的交接處,再從倒數第一個環中的節點取得環的長度。看過別人的解答後,才脫離得先找到環的起始點這個想法。


解題思路

建立鏈節概念

鏈節初始狀態的可能性:有可能只有一個節,或是一條鏈卻沒有成環形。也可能有鏈有環,或是只有環型的狀況。我們不知道目前拿到的鏈結是什麼型態,所以我們要先可以拆解兩個理解的步驟:
Q1. 是否有環
Q2. 判斷環有多長
先有這個想像會比較容易理解後續。

鏈的可能性

鏈的可能性


常見的長短針解法

Q1. 長短針解法:理解「是否有環」的概念

就像是我們的時鐘,時針和分針的走路不一。如果這兩只針在走速不一的狀態下,仍有交疊處,就代表他們的行走路徑能成為一個環型。

如果還有點模糊,稍等一下,待會我們可以從下圖的示例 2、3 來驗證這個概念。


Q2. 視覺化長短針解法:環的長度

下圖是上面提到鏈節的幾種初始狀態可能,在使用長短針解法時的運行方式。

  1. 假設有兩只針,快針(紅色 F) 慢針(綠色 S),長短針一但走入環型範圍,就只會在環形內部環繞繼續行走。若無法前進則停止。
    - 快針:每次走 2 個節點。
    - 慢針:每次走 1 個節點。
    - 數字標示:第 n 步。
    - 橘黃色圈圈:兩只針在環繞環形多次後的交疊處。
  2. 示例 2:有以上概念後,我們可以從示例 2 回推先前提到「如果這兩只針在走速不一的狀態下,仍有交疊處,就代表他們的行走路徑能成為一個環型」這句話。
    當只有鏈沒有環的狀態下,兩針走到無法再行進下一步時就會停止。
    - 慢針(綠色 S)在第 2 步是可以站在節點上的。
    - 快針(紅色 F)在第 1 步位置就已經超過慢針的第 1 步,並且當慢針也抵達相同位置時,但快針卻已經沒有下兩格可以前進所以止步。因為沒有環,所以環長為 0,0 是要返回的答案。
  3. 示例 3:假設題目給我們的是有鏈也有環的鏈結。
    - 慢針(綠色 S)快針(紅色 F)在第 3 步會在相同節點上相遇,3 即是我們要返回的答案。
  4. 示例 4:示例 4 中,慢針(綠色 S)快針(紅色 F)在第 6 步會在相同節點上相遇。若環的長度再做調整,引用上述「長短針一但走入環型範圍,就只會在環形內部環繞繼續行走」的概念,快慢針可能會在走環狀第 n 圈的時候才相遇。總之只要有環就一定會相遇。(例如時鐘時針和分針一天會相遇 24 次)。
長短針解法

長短針解法


解題程式碼

延伸上面圖解的概念,可以以此來實作題目,先判斷是否有環,再取得環的長度

1. 設定快慢針

  • 起始點為 node
  • 慢針:slow,每次使用 getNext() 走 1 格節點。
  • 快針:fast,每次使用兩次的 getNext() ,共計走 2 格節點。

2. 判斷是否有環

  • 帶入情境,如果沒有節點,或無法前進,直接 return 0
  • 每次移動,都判斷兩針所處位置是否同值。若兩針跑完迴圈始終不相等,也 return 0
  • 如果兩針有同值,代表這是一個有環的鏈表。讓我們進入「取得環的長度」的步驟。

3. 取得環的長度

  • Step 2 中的 while (fast && fast.getNext()),如果有找到同值,兩針所處的位置就會停在交叉點上,然後跳入 Step 3 的步驟。
  • 將慢針停止不動,將快針 fast 改為每次只走 1 格,當快針再次回到出發點(與慢針的交差點),就是環型的長度。
function loop_size(node) {	
//如果沒有節點,或是節點只有一個(也就是 node.getNext() 無法取值),則返回 0,因為一定無法成環形
if (!node || !node.getNext()) {
return 0;
}

/* Step 1 建立環形交集點 */
//如果有環形,可以用時鐘長短針的概念來看,先建立快針與慢針
let slow = node;
let fast = node;

/* Step 2 建立環形交集點 */
//當快針當前狀態能取值,並且快針下一格也存在,則迴圈成立
//慢針每次走一格,快針每次走兩格,如果快針和慢針得到同值,則提早離開迴圈
while (fast && fast.getNext()) {
slow = slow.getNext();
fast = fast.getNext().getNext();
if (slow === fast) {
break;
}
}

// 如果迴圈停止時,fast 和 slow 不相等
if (slow !== fast) {
return 0;
}

// Step 3: 固定兩針起始點為同一個點,將快針速度改為每次一格,回到原點的迴圈次數表環型長度
let count = 1;
fast = fast.getNext();
while (fast !== slow) {
fast = fast.getNext();
count++;
}

return count;
}


延伸

留言
avatar-img
Ann Chou的沙龍
19會員
32內容數
從藝術領域轉職到前端工程師,喜歡書寫學習歷程和技術文件,掌握經驗與隨時提取的感覺很好。
你可能也想看
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
題目敘述 All Ancestors of a Node in a Directed Acyclic Graph 給定一個有向無環圖,請找出每個點的祖先,以陣列的形式返回答案。
Thumbnail
題目敘述 All Ancestors of a Node in a Directed Acyclic Graph 給定一個有向無環圖,請找出每個點的祖先,以陣列的形式返回答案。
Thumbnail
題目敘述 題目給定一個鏈結串列中的節點Node,要求我們從鏈結串列中刪除該節點。 題目保證該節點不是tail node。 題目要求我們in-place原位操作。 原本的英文題目敘述 測試範例 Example 1: Input: head = [4,5,1,9], node = 5
Thumbnail
題目敘述 題目給定一個鏈結串列中的節點Node,要求我們從鏈結串列中刪除該節點。 題目保證該節點不是tail node。 題目要求我們in-place原位操作。 原本的英文題目敘述 測試範例 Example 1: Input: head = [4,5,1,9], node = 5
Thumbnail
題目敘述 輸入給定一個鏈結串列的head node。 要求我們進行化簡,只要某個節點的右手邊存在比較大的節點,就刪除掉。 例如 5->2->13->3 5的右手邊有13,所以5刪除掉。 2的右手邊有13,所以2刪除掉。 13的右手邊沒有更大的節點,所以13留著。 3的右手邊沒有更大
Thumbnail
題目敘述 輸入給定一個鏈結串列的head node。 要求我們進行化簡,只要某個節點的右手邊存在比較大的節點,就刪除掉。 例如 5->2->13->3 5的右手邊有13,所以5刪除掉。 2的右手邊有13,所以2刪除掉。 13的右手邊沒有更大的節點,所以13留著。 3的右手邊沒有更大
Thumbnail
給定一個Linked list鏈結串列的Head node, 請判斷這條Linked list是否存在環路(Cycle)? 如果有環路,回傳True。 如果沒有,回傳False。
Thumbnail
給定一個Linked list鏈結串列的Head node, 請判斷這條Linked list是否存在環路(Cycle)? 如果有環路,回傳True。 如果沒有,回傳False。
Thumbnail
Node 對我來說一直是很似懂非懂的概念,因為沒有實際可見的數字或字串實物可以觀察中間步驟,比起其他解題抽象許多。以下解題方法來自網友與 GPT 提供的答案,我想在本文中嘗試自己做視覺化圖解,說明 CodeWars - Can you get the loop ? 的解題思路。
Thumbnail
Node 對我來說一直是很似懂非懂的概念,因為沒有實際可見的數字或字串實物可以觀察中間步驟,比起其他解題抽象許多。以下解題方法來自網友與 GPT 提供的答案,我想在本文中嘗試自己做視覺化圖解,說明 CodeWars - Can you get the loop ? 的解題思路。
Thumbnail
題目敘述 題目會給定一個鏈結串列的起始點,要求我們把其中區間總和為0的部分刪除掉。 例如 1→ 2 → -2 → 3 → 4 裡面有一段是2 → -2 區間總和為零,所以簡化刪除後變成 1→ 3 → 4 題目的原文敘述 測試範例 Example 1: Input: head
Thumbnail
題目敘述 題目會給定一個鏈結串列的起始點,要求我們把其中區間總和為0的部分刪除掉。 例如 1→ 2 → -2 → 3 → 4 裡面有一段是2 → -2 區間總和為零,所以簡化刪除後變成 1→ 3 → 4 題目的原文敘述 測試範例 Example 1: Input: head
Thumbnail
題目敘述 題目會給定一棵二元樹的根結點, 要求我們計算滿足局部路徑節點和=targetSum的數目有多少? 註: 局部路徑節點和 =由節點a往下走到某個節點b,這個區間內的節點值總和 題目的原文敘述 測試範例 Example 1: Input: root = [10,5,-3,3
Thumbnail
題目敘述 題目會給定一棵二元樹的根結點, 要求我們計算滿足局部路徑節點和=targetSum的數目有多少? 註: 局部路徑節點和 =由節點a往下走到某個節點b,這個區間內的節點值總和 題目的原文敘述 測試範例 Example 1: Input: root = [10,5,-3,3
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News