template
<
typename t>
singlylinkednode
*findloopfirst
(singlylinkednode
* head)
// advance slow and fast pointers
s = s-
>
getnext()
; f = f-
>
getnext()
->
getnext()
;if(s == f)
}// reset slow pointer s to the head pointer
s = head;
// find the start point of linked list's loop
while
(true)}
return s;
}
這裡舉乙個例子對演算法加以說明,如圖1所示。演算法說明:設定兩個快慢指標fas
tfast
fast
和s lo
wslow
slow
,快指標每次移動兩個節點,慢指標slo
wslow
slow
每次移動乙個節點。如果鍊錶中有環,則當慢指標移動n=3
n=3n=
3步到鍊錶中的環的起始點(黑點)時,此時快指標和慢指標都進入到環中,由於單向鍊錶的原因,兩個指標將一直在環中無限迴圈執行。當慢指標移動n=3
n=3n=
3步到鍊錶中的環的起始點(黑點)時,快指標肯定位於環中的某個節點,此時可以認為快指標順時針滯後於慢指標。假設這裡滯後z
zz個節點(注意這裡是z
zz個節點不是快指標移動z
zz步,即此時從快指標指向的節點開始迭代取z
zz次nex
tnext
next
指標可以取到黑色節點的指標),由於快指標每次移動兩個節點,慢指標每次移動乙個節點,實際看來每次操作快指標可以追趕慢指標乙個節點。因此經過z
zz次操作後快指標和慢指標將指向同乙個節點。因此如果快慢指標發生碰撞,則說明鍊錶中存在環。
當慢指標移動n=3
n=3n=
3步到鍊錶中的環的起始點,黑點,時,快指標移動了6=2
∗n6=2*n
6=2∗
n步到達紅色節點,也即從鍊錶中的環的起始點,黑點,開始移動算起的第n=3
n=3n=
3個節點(此節點也可以說是從鍊錶中的環的起始點,黑點,開始移動算起的第n=11
n=11
n=11
或第n =19
n=19
n=19
個節點,這是因為環的原因,當n
nn超過loo
psiz
eloopsize
loopsi
ze時就會出現這種情況。因此這裡我們用n=n
%loo
psiz
e=3n=n \% loopsize=3
n=n%lo
opsi
ze=3
來代替此時快指標相對於環的起點移動的節點數。這裡loo
psiz
e=8loopsize =8
loopsi
ze=8
為鍊錶中環的節點個數)這時快指標順時針滯後於慢指標loo
psiz
e−n=
5loopsize-n=5
loopsi
ze−n
=5個節點。上面提到過經過loo
psiz
e−n=
5loopsize-n=5
loopsi
ze−n
=5次操作後快指標和慢指標將指向同乙個節點,綠點,這時綠點距離環的起點,黑點,loo
psiz
e−(l
oops
ize−
n)=n
=3loopsize-(loopsize-n)=n=3
loopsi
ze−(
loop
size
−n)=
n=3個節點,現在煉表頭節點距離環的起點,黑點,也是n=n
%loo
psiz
e=3n=n \% loopsize=3
n=n%lo
opsi
ze=3
個節點。此時將slow指標賦值為頭節點的指標,fas
tfast
fast
指標還是指向綠點,同時fas
tfast
fast
指標和slo
wslow
slow
指標同時向下乙個節點移動,每次移動乙個節點,當兩個指標指向的節點相同時,該節點即為環路的起始處。
該演算法的空間複雜度為o(1)。該演算法的時間複雜度為o(n),n為鍊錶中節點的個數。
圖1.
面試題 02 08 環路檢測
面試題 02.08.環路檢測 給定乙個鍊錶,如果它是有環鏈表,實現乙個演算法返回環路的開頭節點。有環鏈表的定義 在鍊錶中某個節點的next元素指向在它前面出現過的節點,則表明該鍊錶存在環路。示例1 輸入 head 3,2,0,4 pos 1 輸出 tail connects to node inde...
面試題 02 08 環路檢測
給定乙個鍊錶,如果它是有環鏈表,實現乙個演算法返回環路的開頭節點。如果鍊錶中有某個節點,可以通過連續跟蹤 next 指標再次到達,則鍊錶中存在環。為了表示給定鍊錶中的環,我們使用整數 pos 來表示鍊錶尾連線到鍊錶中的位置 索引從 0 開始 如果 pos 是 1,則在該鍊錶中沒有環。注意 pos 不...
Map中環路檢測
map是一種鍵值對的集合,因為鍵值在使用時很有可能呼互換,比方說鍵k1對應的值時v1,然而v1又能作為鍵,而之前的k1將會作為k1對應的值,就產生了環路了,在很多情況下。產生環路可能會使程式無休止的執行下去造成嚴重後果,因此需要檢測環路產生,當新插入的鍵值對會使原先的map產生環路,就拒絕這次插入 ...