1 public ListNode EntryNodeOfLoop(ListNode pHead){ 2 HashSet<ListNode> hs = new HashSet<ListNode>(); 3 while(pHead!=null){ 4 if(!hs.add(pHead))//若是包含了,那麼這個就是入口結點 5 return pHead; 6 pHead = pHead.next; 7 } 8 return null; 9 }
用兩個指針,一個fast指針,每次走兩步,一個slow指針,每次走一步,當fast指針與slow指針相遇時,假設fast指針走了2x,那麼slow指針走了x,因爲有環,那麼爲了便於理解,分爲兩種狀況
oop
一、當fast指針僅僅只比slow指針多走一個環,如圖所示spa
二、第一次相遇的時候,如圖指針
三、這個時候將fast 從新賦值爲開頭,如圖code
四、再走兩次,則找到了環的入口結點blog
從新梳理一下步驟,解題思路接口
a、第一步,找環中相匯點。分別用fast,slow指向鏈表頭部,slow每次走一步,fast每次走二步,直到fast==slow找到在環中的相匯點。ast
b、第二步,找環的入口。接上步,當fast==slow時,fast所通過節點數爲2x,slow所通過節點數爲x,設環中有n個節點,fast比slow多走一圈有2x=n+x; n=x;class
能夠看出slow實際走了一個環的步數,再讓fast指向鏈表頭部,slow位置不變。List
假設鏈表開頭到環接口的距離是y,以下圖所示,那麼x-y表示slow指針走過的除鏈表開頭y在環中走過的距離,那麼slow再走y步,此時fast結點與slow結點相遇,fast == slow ,x-y+y=x = n,即此時slow指向環的入口。循環
解題思路
a、第一步,找環中相匯點。分別用fast,slow指向鏈表頭部,slow每次走一步,fast每次走二步,直到fast==slow找到在環中的相匯點。
b、第二步,找環的入口。接上步,當fast==slow時,fast所通過節點數爲2x,slow所通過節點數爲x,設環中有n個節點,fast比slow多走r圈有2x=rn+x; x=rn;(r爲圈數,n爲一圈的結點數)
能夠看出slow實際走了多個環的步數,再讓fast指向鏈表頭部,slow位置不變。
假設鏈表開頭到環接口的距離是y,那麼x-y表示slow指針走過的除鏈表開頭y在環中走過的距離,那麼slow再走y步,此時fast結點與slow結點相遇,fast == slow ,x-y+y=x = rn,即此時slow指向環的入口。
1 public ListNode EntryNodeOfLoop2(ListNode pHead){ 2 ListNode fast = pHead; 3 ListNode slow = pHead; 4 while(fast != null && fast.next != null){ 5 fast = fast.next.next; 6 slow = slow.next; 7 //當快指針 與 慢指針相遇時 8 if(fast == slow){ 9 fast = pHead; 10 //再次相遇 11 while(fast != slow){ 12 fast = fast.next; 13 slow = slow.next; 14 } 15 return fast; 16 } 17 } 18 return null; 19 }