1. 程式人生 > 其它 >如何判斷一個單鏈表有環?

如何判斷一個單鏈表有環?

判斷一個單鏈表有沒有環?有三種方法。

方法一、窮舉遍歷

如上圖,可見在遍歷帶環的連結串列時,同一個節點總會被遍歷到兩次。那麼基於這一點出發,我們從頭節點開始,遍歷每個節點。在遍歷的過程中,每遍歷到一個新節點的時候,就回頭把新節點之前的所有節點遍歷一遍,然後看新節點的ID是否和之前節點的ID相同,如果相同,那麼說明該節點被遍歷過兩次,連結串列有環,返回true or false。否則就繼續遍歷,然後重複這樣的操作。

方法二、雜湊集合+遍歷

類似於方法一,這次我們不再比較新節點的ID與之前節點的ID,而是利用HashSet的不可重複性使用HashSet儲存曾經遍歷過的節點。每遇到一個新節點,就看HashSet是否包含這個節點,如果發現HashSet已經包含該節點,則說明連結串列有環;如果HashSet當中不包含節點,就把這個新節點存入HashSet,之後進入下一節點,繼續重複剛才的操作。

方法三、快慢指標法

我們給定兩個指標,一個快指標一個慢指標。兩個指標同時遍歷連結串列,快指標每次走兩步,慢指標每次走一步。如果連結串列有環,那麼最終快慢指標總會相遇。如果兩種指標相遇,那麼連結串列有環,返回true.其實快慢指標,為什麼二指標總會相遇呢?這是一個數學問題。有興趣的可以深入學習一下!

程式碼實現

public boolean hasCycle(ListNode head) {
    HashSet<ListNode>   set=new HashSet<ListNode>();//雜湊法
    while(head!=null){
        if (set.contains(head)) {//如果set 可以加入head,返回true.如果不可以,返回false
            return true;//
        }
        set.add(head);
        head = head.next;
   }
   return false;
}
public boolean hasCycle(ListNode head) {

  //快慢指標法
 ListNode slowpoint=head;
 ListNode fastpoint=head;
 while(fastpoint!=null&&fastpoint.next!=null){//while()需要注意,不再使head!=null.當然是快節點以及快節點的下一個節點先到null。有可能是最後一步,有可能最後兩步
    slowpoint=slowpoint.next;//一次走一步
    fastpoint=fastpoint.next.next;//一次走兩步
    if(slowpoint==fastpoint){
        return true;
     }
  
 }
 return false;   
}