環形鍊錶(快慢指標法)

2021-10-24 14:11:30 字數 1784 閱讀 7587

給定乙個鍊錶,判斷鍊錶中是否有環。

如果鍊錶中有某個節點,可以通過連續跟蹤 next 指標再次到達,則鍊錶中存在環。 為了表示給定鍊錶中的環,我們使用整數 pos 來表示鍊錶尾連線到鍊錶中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該鍊錶中沒有環。注意:pos 不作為引數進行傳遞,僅僅是為了標識鍊錶的實際情況。

如果鍊錶中存在環,則返回 true 。 否則,返回 false 。

定義兩個指標,一快一滿。慢指標每次只移動一步,而快指標每次移動兩步。初始時,慢指標在位置 head,而快指標在位置 head.next。這樣一來,如果在移動的過程中,快指標反過來追上慢指標,就說明該鍊錶為環形鍊錶。否則快指標將到達鍊錶尾部,該煉表不為環形鍊錶。

為什麼我們要規定初始時慢指標在位置 head,快指標在位置 head.next,而不是兩個指標都在位置 head?

觀察下面的**,我們使用的是 while 迴圈,迴圈條件先於迴圈體由於迴圈條件一定是判斷快慢指標是否重合,如果我們將兩個指標初始都置於 head,那麼 while 迴圈就不會執行。因此,我們可以假想乙個在 head 之前的虛擬節點,慢指標從虛擬節點移動一步到達 head,快指標從虛擬節點移動兩步到達 head.next,這樣我們就可以使用 while 迴圈了。

當然,我們也可以使用 do-while 迴圈。此時,我們就可以把快慢指標的初始值都置為 head。

**1:

bool hascycle

(struct listnode* head)

struct listnode* slow = head;

struct listnode* fast = head->next;

while

(slow != fast)

slow = slow->next;

fast = fast->next->next;

}return true;

}

**2:

bool hascycle

(struct listnode* head)

struct listnode* slow = head;

struct listnode* fast = head;

do slow = slow->next;

fast = fast->next->next;

}while

(slow != fast)

;return true;

}

時間複雜度:o(n),其中 n 是鍊錶中的節點數。

當鍊表中不存在環時,快指標將先於慢指標到達鍊錶尾部,鍊錶中每個節點至多被訪問兩次。

當鍊表中存在環時,每一輪移動後,快慢指標的距離將減小一。而初始距離為環的長度,因此至多移動 n 輪。

空間複雜度:o(1)o(1)。我們只使用了兩個指標的額外空間。

還有一種思路:思路及演算法

遍歷所有節點,每次遍歷到乙個節點時,判斷該節點此前是否被訪問過。

具體地,我們可以使用雜湊表來儲存所有已經訪問過的節點。每次我們到達乙個節點,如果該節點已經存在於雜湊表中,則說明該鍊錶是環形鍊錶,否則就將該節點加入雜湊表中。重複這一過程,直到我們遍歷完整個鍊錶即可。

這個不太會。

簡單記錄一下。

環形鍊錶II(快慢指標)

題目 題解 假設該表是環形鍊錶,鏈式部分長度為a aa,環形部分長度為b bb。定義快指標fas tfast fast 和慢指標slo wslow slow 先讓fas tfast fast 每次走兩步,slo wslow slow 每次走一步,直到兩者相遇 接著讓fas tfast fast 重置...

環形鍊錶II 快慢指標

參考於 注意要用距離 幾何來理解這道題 使用快慢指標 definition for singly linked list.class listnode def init self,x self.val x self.next none class solution def detectcycle s...

鍊錶 尋找中間結點(快慢指標法)

一般方法 鍊錶這種無法隨機訪問的資料結構,要定位到中間結點的方法通常是先把整個鍊錶遍歷一遍,得到整個鍊錶的長度,再除以2,得到中間結點的位置,接著根據這個位置從頭結點開始找到這個結點,時間複雜度為o 1.5n 具體 如下 definition for singly linked list.struc...