檢測單鏈表是否有環

參考: 判斷一個單鏈表是否有環及環的鏈接點(轉)

給定一個單鏈表,只給出頭指針h: 

1、如何判斷是否存在環? 

2、如何知道環的長度? 

3、如何找出環的連接點在哪裏? 

4、帶環鏈表的長度是多少? 

解法:

1、對於問題1,使用追趕的方法,設定兩個指針slow、fast,從頭指針開始,每次分別前進1步、2步。如存在環,則兩者相遇;如不存在環,fast遇到NULL退出。

2、對於問題2,記錄下問題1的碰撞點p,slow、fast從該點開始,再次碰撞所走過的操作數就是環的長度s。

3、問題3:有定理:碰撞點p到連接點的距離=頭指針到連接點的距離,因此,分別從碰撞點、頭指針開始走,相遇的那個點就是連接點。(證明在後面附註)

     附加:如果每個節點的元素值不重複,所有節點的元素值排序,第一個重複出現的節點就是。

4、問題3中已經求出連接點距離頭指針的長度,加上問題2中求出的環的長度,二者之和就是帶環單鏈表的長度

 

參考:求有環單鏈表中的環長、環起點、鏈表長

1.判斷單鏈表是否有環

  使用兩個slow, fast指針從頭開始掃描鏈表。指針slow 每次走1步,指針fast每次走2步。如果存在環,則指針slow、fast會相遇;如果不存在環,指針fast遇到NULL退出。

  就是所謂的追擊相遇問題:

    

2.求有環單鏈表的環長

   在環上相遇後,記錄第一次相遇點爲Pos,之後指針slow繼續每次走1步,fast每次走2步。在下次相遇的時候fast比slow正好又多走了一圈,也就是多走的距離等於環長。

  設從第一次相遇到第二次相遇,設slow走了len步,則fast走了2*len步,相遇時多走了一圈:

    環長=2*len-len。

3.求有環單鏈表的環連接點位置

  第一次碰撞點Pos到連接點Join的距離=頭指針到連接點Join的距離,因此,分別從第一次碰撞點Pos、頭指針head開始走,相遇的那個點就是連接點。

     

  在環上相遇後,記錄第一次相遇點爲Pos,連接點爲Join,假設頭結點到連接點的長度爲LenA,連接點到第一次相遇點的長度爲x,環長爲R

    第一次相遇時,slow走的長度 S = LenA + x;

    第一次相遇時,fast走的長度 2S = LenA + n*x;

    所以可以知道,LenA + x =  n*R;  LenA = n*R -x;   (理解:LenA = n*(R-1) 【保證回到Pos】 + n-x【保證剩下的距離正好到達Join】)

4.求有環單鏈表的鏈表長

   上述2中求出了環的長度;3中求出了連接點的位置,就可以求出頭結點到連接點的長度。兩者相加就是鏈表的長度。

 

對快慢指針的理解:如果沒有環,快指針一定先走完,兩個指針不會相遇;如果有環,那麼最多隻有一個環,並且兩個指針遲早都會進入環,假定環的長度爲L,當慢指針進入環之後,快指針每次能向前追一步距離,最多隻要L-1步就能追上慢指針所以可以用兩個指針是否相遇來判斷是否有環。

 

參考:單鏈表反轉  算法面試題(1) - 有環鏈表

單鏈表的翻轉是一道很基本的算法題。

        方法1:將單鏈表儲存爲數組,然後按照數組的索引逆序進行反轉。

        方法2:使用三個指針遍歷單鏈表,逐個鏈接點進行反轉。  這個方法的結果很有意思!

        方法3:從第2個節點到第N個節點,依次逐節點插入到第1個節點(head節點)之後,最後將第一個節點挪到新表的表尾。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章