給定乙個單鏈表,判斷其中是否有環,已經是乙個比較老同時也是比較經典的問題,在網上蒐集了一些資料,
然後總結一下大概可以涉及到的問題,以及相應的解法。
首先,關於單鏈表中的環,一般涉及到一下問題:
1.給乙個單鏈表,判斷其中是否有環的存在;
2.如果存在環,找出環的入口點;
3.如果存在環,求出環上節點的個數;
4.如果存在環,求出鍊錶的長度;
5.如果存在環,求出環上距離任意乙個節點最遠的點(對面節點);
6.(擴充套件)如何判斷兩個無環鏈表是否相交;
7.(擴充套件)如果相交,求出第乙個相交的節點;
下面,我將針對上面這七個問題一一給出解釋和相應的**。
對於這個問題我們可以採用「快慢指標」的方法。就是有兩個指標fast和slow,開始的時候兩個指標都指向煉表頭head,然後在每一步操作中slow向前走一步即:slow = slow->next,而fast每一步向前兩步即:fast = fast->next->next。
由於fast要比slow移動的快,如果有環,fast一定會先進入環,而slow後進入環。當兩個指標都進入環之後,經過一定步的操作之後二者一定能夠在環上相遇,並且此時slow還沒有繞環一圈,也就是說一定是在slow走完第一圈之前相遇。
slow每次向前走一步,fast向前追了兩步,因此每一步操作後fast到slow的距離縮短了1步,這樣繼續下去就會使得
兩者之間的距離逐漸縮小:...、5、4、3、2、1、0 -> 相遇。又因為在同乙個環中fast和slow之間的距離不會大於換的長度,因此
到二者相遇的時候slow一定還沒有走完一周(或者正好走完以後,這種情況出現在開始的時候fast和slow都在環的入口處)。
// 檢測環
public static boolean checkcircle(node list)
return false;
}
思路:
如果單鏈表有環,當slow指標和fast指標相遇時,slow指標還沒有遍歷完鍊錶,而fast指標已經在環內迴圈n(n>=1)圈了,假設此時slow指標走了s步,fast指標走了2s步,r為fast在環內轉了一圈的步數,a為從煉表頭到入口點的步數,b為從入口點到相遇點的步數,c為從相遇點再走c步到達入口點,l為整個鍊錶的長度。
slow指標走的步數:
s = a + b
fast指標走的步數:
2s = s + n*r 即:s = n*r
鍊錶的長度:
l = a + b + c = a+r
由上可得:
a + b = n*r = (n - 1)*r + r
而r = l - a,所以:
a + b = (n - 1)*r + l - a
a = (n - 1)*r + l - a - b
而l - a - b = c,所以:
a = (n -1)*r +c
綜上可得:從煉表頭到環入口點等於(n - 1)迴圈內環 + 相遇點到環入口點,於是在煉表頭和相遇點分別設定乙個指標,同時出發,每次各走一步,它們必定會相遇,且第一次相遇的點就是環入口點。
//找到環入口點
public static node findlooppoint(node list)
if(fast == null || fast.next == null)
//如果有環,slow指向連表頭,此時fast指向相遇點
slow = list;
while (slow != fast)
return slow;
}
演算法 檢測是否鍊錶存在環
這兒例子使用快慢指標的辦法實現。h lengthx e m e m lengthy m e lengthz length of circle lengthy lengthz 假定1.開始點是h,環的進入點是e,快指標和慢指標首次相遇的點是m.2.慢指標和快指標首次相遇在m點的時候,是慢指標首次到達m...
鍊錶 檢測是否有環
typedef struct node node,lnode 單鏈表bool isloop lnode ln return true 檢測兩個鍊錶是否相交 一種方法 首尾相交,如果有環則相交 否則不相交。node gettailnode lnode ln if null ln return null...
檢測鍊錶中的環
問題描述 給定乙個鍊錶,檢測該鍊錶中是否存在閉環。要求時間和空間複雜度。問題分析 如果存在環,那麼我們在遍歷鍊錶的時候最終會進入一條無限迴圈中。我們可以把這視為2個人在操作運動,速度快的最終一定會趕上並且遇上速度慢的,也就是速度快的會比速度慢的多跑n整圈。假設a和b倆個物體運動,速度分別為va,vb...