本文參考自《劍指offer》一書,代碼採用Java語言。html
更多:《劍指Offer》Java實現合集 java
一個鏈表中包含環,如何找出環的入口結點?例如,在圖3.8的鏈表中,環的入口結點是結點3。oop
1.肯定鏈表是否有環:經過兩個不一樣速度的指針肯定,當兩個指針指向同一個結點時,該結點爲環中的一個結點。post
2.肯定環中結點的數目n:指針走一圈,邊走邊計數測試
3.找到環的入口:從頭結點開始,經過兩個相差爲n的指針來獲得(即尋找鏈表中倒數第n個結點)this
更簡單的思路:【LeetCode】142. Linked List Cycle IIurl
測試算例 spa
1.功能測試(鏈表包含與不包含環;鏈表有多個或一個結點)指針
2.特殊測試(頭結點爲null)htm
package _23; /** * * @Description 鏈表中環的入口結點 * * @author yongh * @date 2018年10月15日 下午2:35:14 */ //題目:一個鏈表中包含環,如何找出環的入口結點?例如,在圖3.8的鏈表中, //環的入口結點是結點3。 /* * 思路:1.肯定鏈表是否有環:經過兩個不一樣速度的指針肯定 * 2.肯定環中結點的數目n:指針走一圈,邊走邊計數 * 3.找到環的入口:從頭結點開始,經過兩個相差爲n的指針來獲得(即尋找鏈表中倒數第n個結點) */ public class EntryNodeInListLoop { public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } /* * 肯定鏈表是否有環,採用快慢指針肯定 * 返回值表明快慢指針相遇時的結點,返回null表明鏈表無環 */ private ListNode meetingNode(ListNode head) { if(head==null) return null; ListNode pSlow=head; ListNode pFast=head; while(pFast!=null) { pSlow=pSlow.next; pFast=pFast.next; if(pFast!=null) pFast=pFast.next; if(pSlow!=null && pSlow==pFast) return pSlow; } return null; } /** * 計算環中入口結點 */ public ListNode entryNodeOfLoop(ListNode head) { ListNode meetingNode=meetingNode(head); if(meetingNode==null) return null; //計算環中結點的數目 int count=1; //環中結點的數目 ListNode pNode1 = meetingNode.next; while(pNode1!=meetingNode){ count++; pNode1=pNode1.next; } //先移動pNode1,次數爲count pNode1=head; for(int i=1;i<=count;i++) { pNode1=pNode1.next; } ListNode pNode2=head; while(pNode1!=pNode2) { pNode1=pNode1.next; pNode2=pNode2.next; } return pNode1; } }
1.經過兩個不一樣速度的指針能夠肯定鏈表中是否有環
2.相差n步的兩個指針能夠找到倒數第n個結點(鏈表中倒數第k個結點)
3.複雜問題分解成爲幾個簡單問題(本題分爲三步:找出環中任一結點;獲得環的個數;找到入口結點)