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


本文參考自《劍指offer》一書,代碼采用Java語言。

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

題目 

  一個鏈表中包含環,如何找出環的入口結點?例如,在圖3.8的鏈表中,環的入口結點是結點3。

思路

  1.確定鏈表是否有環:通過兩個不同速度的指針確定,當兩個指針指向同一個結點時,該結點為環中的一個結點。

  2.確定環中結點的數目n:指針走一圈,邊走邊計數

  3.找到環的入口:從頭結點開始,通過兩個相差為n的指針來得到(即尋找鏈表中倒數第n個結點)

  更簡單的思路:【LeetCode】142. Linked List Cycle II

測試算例 

  1.功能測試(鏈表包含與不包含環;鏈表有多個或一個結點)

  2.特殊測試(頭結點為null)

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實現合集  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM