經典演算法題 判斷單鏈表是否成環及尋找成環節點

2021-10-11 02:42:20 字數 2970 閱讀 2768

判斷單鏈表是否成環是乙個計算機領域的經典演算法問題

如何通過程式判斷傳入的鍊錶是否存在環,並且求出環長度、成環點等問題

下面就是乙個存在環的單鏈表

最簡單的方法是建立乙個雜湊表,將每個節點的位址都儲存起來,如果某個節點的位址出現在了雜湊表中,那麼首次出現的那個節點就是我們要找的成環的起點了

1)**示例

class listnode:

def __init__(self, x):

self.val = x

self.next = none

def get_start_cycle(phead):

nodedict = {}

while phead is not none:

if nodedict.get(phead) is not none:

return phead

nodedict[phead] = 1

phead = phead.next

return none

2)時間空間複雜度顯然,在最壞情況下,需要遍歷整個鍊錶,所以時間複雜度為 o(n),空間複雜度為 o(n)

有過一定生活經驗的人馬上就會想到,在操場的圓形賽道上跑步與在街道上跑馬拉松有什麼不同,那就是在操場的賽道上,跑得快的人會從後面追上跑得慢的人

那麼,對於單鏈表來說,我們就可以用兩個指標,乙個快指標,乙個慢指標,從起點出發,快指標如果在出發後追上了慢指標,那就說明單鏈表是存在環的

1)步長選取

那麼快指標要選取多大的步長呢?答案是 2,如果選取大於 2 的步長,就會出現快指標直接越過慢指標的情況

typedef struct linkednode  linkednode;

int is_cycle(linkednode *head)

linkednode *slow = head->next, *quick = head->next->next;

while (quick != null && quick->next != null)

quick = quick->next->next;

slow = slow->next;

}return 0;

}

因為快指標繞一圈,慢指標只能繞半圈,所以我們可以得出兩指標相遇時,慢指標一定沒有繞滿一圈

而不成環的情況下,快指標一定先到達終點,所以時間複雜度為 o(n)

整個過程沒有額外分配空間,所以空間複雜度是 o(1)

假設環長為 d,初始距入口點為 n,入口點距相遇點為 m

假設此時快指標已經繞了 k 圈,那麼我們可以得到公式:

m+n = k*d

但是,我們要求的是入口點距起始點的距離 m,所以我們需要進行移項:

m = k*d-n

因為兩指標相遇時,快指標一定至少已經繞滿一圈,所以 k 一定大於等於 1,而 d - n 就是從相遇點繼續前進到起始點的距離,所以我們可以進一步分解 k*d:

m = (k-1)*d + (d-n)

因此,我們可以發現,從起始點出發到成環點的距離與相遇點出發到成環點的距離之間只差 (k-1) 個

也就是說,兩個指標如果以相同步長分別從起始點與相遇點出發,相遇時一定在成環點

linkednode *get_cycle_start_node(linkednode *head) 

linkednode *slow = head->next, *quick = head->next->next;

while (quick != null && quick->next != null)

return slow;

}quick = quick->next->next;

slow = slow->next;

}return null;

}

我們看到,無論自相遇點出發的指標繞環多少圈,自起始點出發的指標最多遍歷 n-1 個元素,所以其時間複雜度也是 o(n) 的,而空間複雜度為 o(1)

三十六計裡有一計 -- 過河拆橋

在已知單鏈表成環的前提下,我們每走一步都把前面的路拆掉,那麼當我們發現無路可走時,那就說明我們又回到了原來的路上,那個點自然就是成環點了

}這個演算法先判斷是否成環,後從頭到尾最多遍歷 n-1 個元素,所以時間複雜度也是 o(n),而空間複雜度為 o(1)

判斷單鏈表是否成環演算法

演算法思想 定義兩個指標p,q,其中p每次向前移動一步,q每次向前移動兩步,所以就成p為慢指標,q為快指標。那麼如果單鏈表存在環,則p和q進入環後一定會在某一點相遇,因為進入環後就會一直迴圈下去,否則q將首先遇到null,就說明不存在環。這裡肯定會有人問,就是為什麼當單鏈表存在環時,p和q一定會相遇...

判斷單鏈表是否成環

成環 可以是迴圈單鏈表,即首位相連 也可以是部分成環,即尾部和其他節點相連。判斷是否成環 使用快慢指標遍歷鍊錶 慢指標 從頭節點開始,一次跳乙個節點。快指標 從頭節點開始,一次跳兩個節點。如果是成環的,這兩個指標一定會相遇。如上圖所示,藍色表示慢指標,紅色表示快指標,他們在經過4次遍歷後相遇,也就是...

判斷單鏈表是否有環

1 如何判斷乙個鍊錶是不是這類鍊錶?2 如果鍊錶為存在環,如果找到環的入口點?解答 一 判斷鍊錶是否存在環,辦法為 設定兩個指標 fast,slow 初始值都指向頭,slow每次前進一步,fast每次前進二步,如果鍊錶存在環,則fast必定先進入環,而slow後進入環,兩個指標必定相遇。當然,fas...