如何判斷鍊錶有環

2021-10-10 05:52:56 字數 2037 閱讀 2088

題目描述:有乙個單向鍊錶,鍊錶中有可能出現「環」,如下圖,那麼,如何用程式來判斷該鍊錶是否為有環鏈表呢?

方法一:

從頭節點開始遍歷每乙個節點,每遍歷乙個新節點就從頭檢查到新節點之前的所有節點,如果和該新節點的值有重複,則證明該節點被遍歷過兩次,鍊錶有環;如果不存在與新節點相同值的節點,就繼續遍歷下乙個新節點,繼續重複上述操作。

假設鍊錶的節點數量為n,則該解法時間複雜度為o(

方法二:

引入雜湊表,建立乙個以節點id為key的set集合,用來儲存曾經遍歷過的節點。然後同樣從頭遍歷單鏈表中的每乙個節點,每遍歷乙個節點,都用新節點與set集合中儲存的節點進行比較,如果發現set中存在與之相同的節點id,則說明鍊錶有環,如果不存在,就把這個節點id存入set集合中,繼續遍歷下乙個節點,重複上述操作。

兩種方法本質區別是使用了set作為額外的快取。

假設鍊錶節點數量為n,則該解法的時間複雜度為o(n),由於建立了額外儲存空間,空間複雜度為o(n)。

方法三:

模擬追及問題,首先建立兩個指標p1和p2(在python中就是兩個物件引用),讓它們同時指向鍊錶的頭節點,然後開始迴圈遍歷節點,其中p1每次向後移動1個節點,p2每次向後移動2個節點,然後比較兩個指標指向的節點是否相同,如果相同,則可以判斷出煉表有環,如果不同,則繼續下一次迴圈。

假設鍊錶節點數量為n,則該解法的時間複雜度為o(n),由於未建立額外儲存空間,空間複雜度為o(1)。

python**實現如下:

class node:

def __init__(self, data):

self.data = data

self.next = none

def is_cycle(head):

p1 = head

p2 = head

while p2 is not none and p2.next is not none:

p1 = p1.next

p2 = p2.next.next

if p1 == p2:

return true

return false

node1 = node(5)

node2 = node(3)

node3 = node(7)

node4 = node(2)

node5 = node(6)

node1.next = node2

node2.next = node3

node3.next = node4

node4.next = node5

node5.next = node2

print(is_cycle(node1))

擴充套件問題:如果鍊錶有環,如何求出環的長度以及入環節點?

求環長:當兩個指標首次相遇,證明鍊錶有環後,兩指標繼續迴圈前進,並統計前進的迴圈次數,直到兩個指標第2次相遇。此時,統計的前進次數就是環長。

求入環節點:假設從煉表頭節點到入環點距離是d,入環點到首次相遇點距離是s1,首次相遇點到入環點為s2。

由結論可得,把其中乙個指標放回頭節點的位置,另乙個指標保持在首次相遇點,兩個指標都是每次向前走1步。那麼它們最終相遇的節點,就是入環節點。

如何判斷鍊錶有環

假設存在環,環前共l個節點,環中共c個節點.設乙個慢指標起始位置為a,速度為1,快指標起始位置為b,速度為2.t時間後,二者相遇,可列方程 a t l mod c b 2 t l mod c 即t a b mod c 該模線性方程必定有解.所以無論a,b的起始位置如何,二者總是會相遇的.struct...

如何判斷鍊錶有環?

題目描述 如果有乙個單向鍊錶,鍊錶當中有可能出現 環 就像下圖這樣,如何判斷這個鍊錶是有環鏈表?方案一 暴力法 從頭節點,依次遍歷單鏈表的每乙個節點,每到乙個新的節點就頭節點重新遍歷之前的所有的節點,對比此時的節點,如果相同,證明該節點遍歷過兩次,以此說明鍊錶是有環的 偽 node p head.n...

如何判斷鍊錶有環?

參考 程式設計師小灰 參考2 漫畫演算法 如何判斷鍊錶有環?package chapter5.part2 public class linkedlistcycletest else private static boolean iscycle node head return false priva...