Linked List Cycle leetcode java (連結串列檢測環)

愛做飯的小瑩子發表於2014-07-23

題目:

Given a linked list, determine if it has a cycle in it.

Follow up:
Can you solve it without using extra space?

 

題解:

 這道題連帶著II是很經典的,在看CC150時候,糾結這個問題糾結了很久。在讀了很多網上資料還有書的講解以及和別人討論之後,對這個專題終於明白了。

 

 這一問只需要判斷連結串列是否有環。

 當連結串列沒有環時是很好判斷的,讓一個指標一直往後走,遇見null了自然就沒有環。

 而如何判斷有環,那麼就需要引入Faster和Slower的概念了(也是一種雙指標方法)。顧名思義,同個時間Faster走的比Slower走的多。一般來說,Slower每次走一步,Faster每次走2步(通常這個概念可以判斷連結串列中間點)。在這裡,Faster和Slower同時從起點遍歷連結串列,如果有環那麼Slower和Faster肯定會相遇。

 為什麼他倆肯定能相遇呢?萬一一個把一個超了但是沒相遇咋辦?

 直覺和生活經驗告訴我,他倆肯定能相遇,比如在操場跑圈,一個快的一個慢的同時開始跑,一直跑,快的肯定能跟慢的相遇。不過有更嚴謹的說法就更有說服力了。

下面我就引用一下CC150裡面外加我的完善來說明怎麼證明的這個問題:

 假設Faster確實把Slower超了而且他倆還沒相遇(類似Faster一下邁了2步,Slower一下邁了一步,Faster超了Slower,但是倆人並沒遇上)。那麼就假設Faster現在在 i+1 位置而Slower在 i 位置。那麼前一時刻,Slower肯定是在 i-1 位置,而Faster肯定在(i+1)-2位置,所以前一時刻,倆人都在 i-1 位置,相遇了。

還有一種情況就是Faster在i+2位置而slower在i位置,那麼前一時刻,Faster在i位置,而Slower在 i-1位置。這樣問題又迴歸到上面那種情況了(再往前一時刻,Faster在i-2位置,Slower在i-1-1位置,相遇)。

所以,這就證明Runner和Faster在有環的連結串列中肯定會相遇。

程式碼工作就很簡單了,如下:

 1     public boolean hasCycle(ListNode head) {
 2         if(head == null || head.next == null)
 3             return false;
 4         
 5         ListNode Faster = head, Slower = head;
 6         
 7         while(Faster.next!=null && Faster.next.next!=null){
 8             Slower = Slower.next;
 9             Faster = Faster.next.next;
10             
11             if(Faster == Slower)
12                 return true;
13         }
14         return false;
15     }

 

相關文章