【解題筆記 - 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
留言分享你的想法!
avatar-img
Ann Chou的沙龍
17會員
29內容數
從藝術領域轉職到前端工程師,喜歡書寫學習歷程和技術文件,掌握經驗與隨時提取的感覺很好。
你可能也想看
Thumbnail
TOMICA第一波推出吉伊卡哇聯名小車車的時候馬上就被搶購一空,一直很扼腕當時沒有趕緊入手。前陣子閒來無事逛蝦皮,突然發現幾家商場都又開始重新上架,價格也都回到正常水準,估計是官方又再補了一批貨,想都沒想就立刻下單! 同文也跟大家分享近期蝦皮購物紀錄、好用推薦、蝦皮分潤計畫的聯盟行銷!
Thumbnail
TOMICA第一波推出吉伊卡哇聯名小車車的時候馬上就被搶購一空,一直很扼腕當時沒有趕緊入手。前陣子閒來無事逛蝦皮,突然發現幾家商場都又開始重新上架,價格也都回到正常水準,估計是官方又再補了一批貨,想都沒想就立刻下單! 同文也跟大家分享近期蝦皮購物紀錄、好用推薦、蝦皮分潤計畫的聯盟行銷!
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
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
Thumbnail
題目敘述 題目會給定我們一顆二元樹的根結點,要求我們計算這棵樹的好結點Good node有多少個? 好結點Good node的定義: 某個節點v是好結點,假如從Root node根結點 到 結點v沿途的節點值都小於等於節點v的節點值。 如果還是覺得很模糊,看下方的測試範例就可以很清楚了解
Thumbnail
題目敘述 題目會給定我們一顆二元樹的根結點,要求我們計算這棵樹的好結點Good node有多少個? 好結點Good node的定義: 某個節點v是好結點,假如從Root node根結點 到 結點v沿途的節點值都小於等於節點v的節點值。 如果還是覺得很模糊,看下方的測試範例就可以很清楚了解
Thumbnail
題目敘述 題目會給定我們一條鏈結串列Linked list的起始節點,要求我們刪除Linked List正中央的節點。 註: 正中央的節點,題目定義為索引為floor( 串列長度 / 2 ) 的節點,索引從零(Head Node)出發開始數。 例如 1 -> 2 -> 3 -> 4 鏈結
Thumbnail
題目敘述 題目會給定我們一條鏈結串列Linked list的起始節點,要求我們刪除Linked List正中央的節點。 註: 正中央的節點,題目定義為索引為floor( 串列長度 / 2 ) 的節點,索引從零(Head Node)出發開始數。 例如 1 -> 2 -> 3 -> 4 鏈結
Thumbnail
題目敘述 題目會給定一顆二元樹的根結點Root node,和指定的目標值targetSum。 問我們能不能從二元樹裡面找到一條從根結點到葉子結點的路徑,其路徑上的節點值總和恰好為targetSum? 可以的話,返回True。 無解的話,返回False。 題目的原文敘述 測試範例 E
Thumbnail
題目敘述 題目會給定一顆二元樹的根結點Root node,和指定的目標值targetSum。 問我們能不能從二元樹裡面找到一條從根結點到葉子結點的路徑,其路徑上的節點值總和恰好為targetSum? 可以的話,返回True。 無解的話,返回False。 題目的原文敘述 測試範例 E
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News