1. 程式人生 > >一個鏈表中包含環,請找出該鏈表的環的入口結點

一個鏈表中包含環,請找出該鏈表的環的入口結點

size alt 情況 每次 png -1 節點 pan mage

方法一、用HashSet來解決

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,由於有環,那麽為了便於理解,分為兩種情況

情況一:

1、當fast指針僅僅只比slow指針多走一個環,如圖所示

技術分享

2、第一次相遇的時候,如圖

技術分享

3、這個時候將fast 重新賦值為開頭,如圖

技術分享

4、再走兩次,則找到了環的入口結點

技術分享

重新梳理一下步驟,解題思路

a、第一步,找環中相匯點。分別用fast,slow指向鏈表頭部,slow每次走一步,fast每次走二步,直到fast==slow找到在環中的相匯點。

b、第二步,找環的入口。接上步,當fast==slow時,fast所經過節點數為2x,slow所經過節點數為x,設環中有n個節點,fast比slow多走一圈有2x=n+x; n=x;

可以看出slow實際走了一個環的步數,再讓fast指向鏈表頭部,slow位置不變。

假設鏈表開頭到環接口的距離是y,如下圖所示,那麽x-y表示slow指針走過的除鏈表開頭y在環中走過的距離,那麽slow再走y步,此時fast結點與slow結點相遇,fast == slow ,x-y+y=x = n,即此時slow指向環的入口。

技術分享

情況二、當fast比slow 多走n個環

技術分享

解題思路

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     }

一個鏈表中包含環,請找出該鏈表的環的入口結點