題目描述:有乙個單向鍊錶,鍊錶中有可能出現「環」,如下圖,那麼,如何用程式來判斷該鍊錶是否為有環鏈表呢?
方法一:
從頭節點開始遍歷每乙個節點,每遍歷乙個新節點就從頭檢查到新節點之前的所有節點,如果和該新節點的值有重複,則證明該節點被遍歷過兩次,鍊錶有環;如果不存在與新節點相同值的節點,就繼續遍歷下乙個新節點,繼續重複上述操作。
假設鍊錶的節點數量為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...