[英]How to find loop-node of a linkedlist with a loop?
這個問題與尋找 2 個鏈表的交集有點不同。
考慮一個帶有循環的鏈表: A - B - C - D - E - F - C
。
如果節點A
是函數的輸入,則它應該返回C
。
由於我不知道如何稱呼C
,因此我使用了問題中所見的術語循環節點C
。 盡管 O(n 2 ) 項看起來很明顯,但有沒有辦法找到復雜度較低的循環節點?
不允許使用 O(n) 的哈希表/額外空間。
有一個使用兩個指針的簡單方法。第一個指針增加一個,第二個增加慢指針速度的兩倍。
所以你的情況下的鏈表實際上是A->B->C->D->E->F->C
意味着 F 再次指向 C.So 方法如下
1.繼續增加兩個pointers
直到它們匹配。所以在上面的情況下我們會有這些步驟
慢指針:ABCDE
快速指針:ACECE
所以我們在 E 處停止,這表明存在一個循環。現在我們需要找到循環節點。
現在從 E 將慢指針移動到鏈表的開頭,並創建一個指向 E 並遞增 1 的新指針。這兩個指針相交的點實際上是循環節點。所以在我們的例子中
從頭開始的指針:ABC 新指針:EFC
因此,如您所見,它們在 C 處相遇,我們完成了在鏈表中查找循環節點的工作。
更新:對於這種方法的數學證明,請參考這個精彩的問題,並查看@Jim Lewis 的回答以及答案下方的所有評論。 解釋在循環鏈表中查找循環起始節點是如何工作的?
Floyd 的循環尋找算法是最簡單的 算法,而且通常是“規范答案”,因為這是每個人在大學里學到的東西(也許是因為它簡單、優雅且富有洞察力)。
人們還經常聲稱運行時不可改進,但事實並非如此——大 Oh 可能無法改進,但這只能告訴我們一些關於最壞情況下漸近行為的信息。 Brent 算法在實踐中更快,同時仍然使用恆定的空間量。 還有更多的算法,例如 Gosper's Loop Detection 或 Sedgewick、Szymanski 和 Yao's 算法或k-stacks 算法,它們都使用一定的(低,但理論上是非恆定的)空間量。 實際上,對於鏈表的任何實際實現,空間量仍然是恆定的,因為您的指針將是固定大小的。 例如,對於 32 位指針,Gosper 的循環檢測將使用 33 個字的空間(加上可能額外的幾個,取決於您想要計數的內容)。
Floyd 的算法很好,但不一定是 The Answer (tm) 。 需要做出選擇和權衡。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.