鍊錶演算法 檢測環

2021-08-31 20:40:15 字數 1791 閱讀 8964

給定乙個單鏈表,判斷其中是否有環,已經是乙個比較老同時也是比較經典的問題,在網上蒐集了一些資料,

然後總結一下大概可以涉及到的問題,以及相應的解法。

首先,關於單鏈表中的環,一般涉及到一下問題:

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...