【Java】 劍指offer(23) 鏈表中環的入口結點

本文參考自《劍指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

Java代碼

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.複雜問題分解成爲幾個簡單問題(本題分爲三步:找出環中任一結點;獲得環的個數;找到入口結點)

  

更多:《劍指Offer》Java實現合集 

相關文章
相關標籤/搜索