fast走過的步數 = s + n*r(s + 在環上多走的n圈),則有下面的等式:
2*s = s + n * r ; (1) => s = n*r (2)
如果假設整個鍊錶的長度是l,入口和相遇點的距離是x(如上圖所示),起點到入口點的距離是a(如上圖所示),則有:
a + x = s = n * r; (3) 由(2)推出
a + x = (n - 1) * r + r = (n - 1) * r + (l - a) (4) 由環的長度 = 鍊錶總長度 - 起點到入口點的距離求出
a = (n - 1) * r + (l -a -x) (5)
從鍊錶起點head開始到入口點的距離a,與從slow和fast的相遇點(如圖)到入口點的距離相等。
思路1:記錄下相遇節點存入臨時變數tempptr,然後讓slow(或者fast,都一樣)繼續向前走slow = slow -> next;一直到slow == tempptr; 此時經過的步數就是環上節點的個數;
思路2:從相遇點開始slow和fast繼續按照原來的方式向前走slow = slow -> next; fast = fast -> next -> next;直到二者再次專案,此時經過的步數就是環上節點的個數 。
fast和slow沒一次操作都會使得兩者之間的距離較少1。我們可以把兩者相遇的時候看做兩者之間的距離正好是整個環的長度r。因此,當再次相遇的時候所經過的步數正好是環上節點的數目。
鍊錶長度l = 起點到入口點的距離 + 環的長度r;
對於環上任意的乙個點ptr0, 我們要找到它的」對面點「,可以這樣思考:同樣使用上面的快慢指標的方法,讓slow和fast都指向ptr0,每一步都執行與上面相同的操作(slow每次跳一步,fast每次跳兩步),當fast = ptr0或者fast = prt0->next的時候slow所指向的節點就是ptr0的」對面節點「。
為什麼是這樣呢?我們可以這樣分析:
如上圖,我們想像一下,把環從ptro處展開,展開後可以是無限長的(如上在6後重複前面的內容)如上圖。
現在問題就簡單了,由於slow移動的距離永遠是fast的一般,因此當fast遍歷玩整個環長度r個節點的時候slow正好遍歷了r/2個節點,也就是說,此時正好指向距離ptr0最遠的點。
6.(擴充套件)如何判斷兩個無環鏈表是否相交;
7.(擴充套件)如果相交,求出第乙個相交的節點;
假設有連個鍊錶lista和listb,如果兩個鍊錶都無環,並且有交點,那麼我們可以讓其中乙個鍊錶(不妨設是lista)的為節點連線到其頭部,這樣在listb中就一定會出現乙個環。因此我們將問題6和7分別轉化成了問題1和2.
單鏈表中的環
問題一 鍊錶中是否存環?問題二 鍊錶中環的入口結點是哪個?問題三 鍊錶中環的結點數目 環的長度 是多少?解答思路 問題一 如果有兩個頭結點指標,乙個走的快,乙個走的慢,那麼若干步以後,快的指標總會超過慢的指標一圈。問題二 假設問題一中兩個不同步速遍歷的指標為p和q,其中p的步速為2,q的步速為1,假...
單鏈錶環問題
給定乙個單鏈表,只給出頭指標h 1 如何判斷是否存在環?2 如何知道環的長度?3 如何找出環的連線點在 4 帶環鍊錶的長度是多少?5 如果存在環,求出環上距離任意乙個節點最遠的點 對面節點 6 擴充套件 如何判斷兩個無環鏈表是否相交 7 擴充套件 如果相交,求出第乙個相交的節點 解法 1 對於問題1...
約瑟夫環 單鏈表
此演算法將頭指標head也進行data賦值 include typedef struct node 定義結構體 linknode,link int main void josephu link head,int n,int k,int m 此演算法將頭指標head賦予data值,以便於迴圈鍊錶結點的...