這個問題可以衍生出很多擴充套件性的問題:
給定乙個單鏈表,
1.如何判斷是否有環
2.如何知道環的長度
3.如何找到環的入口
4.整個鍊錶的長度是多少
相應的解法如下:
問題1時後面所有問題的根問題,解決這個問題一般用到快慢指標,乙個fast指標,乙個slow指標,兩個指標同時指向單鏈表的頭結點,然後fast指標一次移動兩步,slow指標則一次移動一步,如果最終兩個指標相遇,則說明鍊錶有環,否則無環。
1那為什麼這樣就能判斷鍊錶中是否存在環呢?bool hascycle(listnode *head)
13else
14return
false;15
if(fast==slow)
16return
true;17
}18return
false
;19 }
假定單鏈表的長度為n,並且該單鏈表是環狀的,那麼第i次迭代時,p指向元素i mod n,q指向2i mod n。因此當i≡2i(mod n)時,p與q相遇。而i≡2i(mod n) => (2i - i) mod n = 0 => i mod n = 0 => 當i=n時,p與q相遇。這裡乙個簡單的理解是,p和q同時在操場跑步,其中q的速度是p的兩倍,當他們兩個同時出發時,p跑一圈到達起點,而q此時也剛 好跑完兩圈到達起點。
那麼當p與q起點不同呢?假定第i次迭代時p指向元素i mod n,q指向k+2i mod n,其中0(i+k) mod n = 0 => 當i=n-k時,p與q相遇。
這裡的關鍵是理解,其實,快指標和慢指標雖然一開始不在環裡,但是當他們都進入環裡的時候,其實這個問題的模型相當於兩個指標在環裡起點不同的模型。
懂了這點,後續很多證明都好理解了。
擴充套件閱讀:
推廣:1. 如果兩個指標的速度不一樣,比如p,q,( 0
sp(i) = pi
sq(i) = k + qi
如果兩個要相交於乙個節點,則 sp(i) = sq(i) => (pi) mod n = ( k+ qi ) mod n =>[ (q -p)i + k ] mod n =0
=> (q-p)i + k = nn [n 為自然數]
=> i = (nn -k) /(p-q)
i取自然數,則當 p,q滿足上面等式 即 存在乙個自然數n,可以滿足nn -k 是 p - q 的倍數時,保證兩者相交。
特例:如果q 是p 的步長的兩倍,都從同乙個起點開始,即 q = 2p , k =0, 那麼等式變為: nn=i: 即可以理解為,當第i次迭代時,i是圈的整數倍時,兩者都可以交,交點就是為起點。
2.如何判斷單鏈表的環的長度?
這個比較簡單,知道q 已經進入到環裡,儲存該位置。然後由該位置遍歷,當再次碰到該q 位置即可,所迭代的次數就是環的長度。
3. 如何找到鍊錶中第乙個在環裡的節點?
假設鍊錶長度是l,前半部分長度為k-1,那麼第乙個再環裡的節點是k,環的長度是 n, 那麼當q=2p時, 什麼時候第一次相交呢?當q指標走到第k個節點時,q指標已經在環的第 k mod n 的位置。即p和q 相差k個元素,從不同的起點開始,則相交的位置為 n-k, 則有了下面的圖:
從圖上可以明顯看到,當p從交點的位置(n-k) ,向前遍歷k個節點就到到達環的第乙個幾點,節點k.
演算法就很簡單: 乙個指標從p和q 中的第一次相交的位置起(n-k),另外乙個指標從煉表頭開始遍歷,其交點就是鍊錶中第乙個在環裡的交點。
下面是另外一種證明方法:
假設p和q分別以速度為v1和v2前進。如果有環,設指標p和q第一次進入環時,他們相對於環中第乙個節點的偏移位址分別為a和b(可以把偏移位址理解為節點個數)。如上圖。
這樣,可以看出,鍊錶有環的充要條件就是某一次迴圈時,指標p和q的值相等,就是它們相對環中首節點的偏移量相等。
我們設環中的結點個數為n,程式迴圈了m次。
由此可以有下面等式成立:(mod(n)即對n取餘)
(a+m*v1)mod(n) = (b+m*v2) mod(n)
設等式左邊mod(n)的最大整數為k1,等式右邊mod(n)的最大整數為k2,則
(a+m*v1)-k1*n = (b+m*v2)-k2*n
m= |((k2-k1)*n+a-b)/( v2-v1)| ①
如果是等式①成立,就要使迴圈次數m為一整數。顯然如果v2-v1為1,則等式成立。
這樣p和q分別以速度為v1和v2且|v2-v1|為1時,按以上演算法就可找出鍊錶中是否有環。
2、對於問題2,記錄下問題1的碰撞點p,slow、fast從該點開始,再次碰撞所走過的運算元就是環的長度s。
3、問題3:有定理:碰撞點p到連線點的距離=頭指標到連線點的距離,因此,分別從碰撞點、頭指標開始走,相遇的那個點就是連線點。
4、問題3中已經求出連線點距離頭指標的長度,加上問題2中求出的環的長度,二者之和就是帶環單鏈表的長度
如何判斷鍊錶是否有環 鍊錶是否有環的判斷
對於鍊錶是否存在環,有三個問題需要考慮 1.是否有環 2.入環節點 3.環的長度 第一種方法快慢指標法,也稱之為龜兔演算法,設定兩個指標,慢指標和快指標。最開始均指向鍊錶的頭節點,之後,快指標每次後移兩個節點,慢指標每次後移乙個節點。1.如果快指標指向空,則鍊錶無環 2.若快指標和慢指標再次指向乙個...
如何判斷鍊錶是否有環
背景 例如在乙個大的系統中,如果出現兩個鍊錶相交的情況,而且釋放其中乙個鍊錶所有的節點,那就會造成資訊的丟失,並且釋放其中乙個鍊錶的所有節點,那就會造成資訊的丟失並且與之相交的鍊錶也會受到影響,如下圖 給出兩個單鏈表的頭指標 h1,h2 假設兩個鍊錶均不帶環 方法一 判斷第乙個鍊錶所有的節點是否在第...
如何判斷鍊錶中是否有環
今天面試被問住了,很慚愧啊,回來上網查了一下思路。自己寫了點程式。1.如何判斷是否有環?如果有兩個頭結點指標,乙個走的快,乙個走的慢,那麼若干步以後,快的指標總會超過慢的指標一圈。2.如何計算環的長度?第一次相遇 超一圈 時開始計數,第二次相遇時停止計數。3.如何判斷環的入口點 碰撞點p到連線點的距...