1. 程式人生 > >劍指Offer面試題56:連結串列中環的入口節點 Java實現

劍指Offer面試題56:連結串列中環的入口節點 Java實現

/**************************************************************      
* Copyright (c) 2016, 
* All rights reserved.                   
* 版 本 號:v1.0                   
* 題目描述:連結串列中環的入口節點
*   	        一個連結串列中包含環,如何找出環的入口節點?例如,下圖中的入口節點是3.
*   		1->2->3->4->5->6
*   			  ^  	   |
*   			  | 	   |
*   			  ----------	   
*   
* 輸入描述:無
* 程式輸出:環中節點數是: 4
*			連結串列中環的入口節點是:3
* 問題分析: 無
* 演算法描述:可以用兩個指標來解決這個問題。先定義兩個指標P1和P2指向連結串列的頭結點。如果連結串列中環有n個結點,
* 			指標P1在連結串列上向前移動n步,然後兩個指標以相同的速度向前移動。當第二個指標指向環的入口結點時,
* 			第一個指標已經圍繞著環走了一圈又回到了入口結點。
*		  剩下的問題就是如何得到環中結點的數目。我們在面試題15的第二個相關題目時用到了一快一慢的兩個指標。
*			如果兩個指標相遇,表明連結串列中存在環。兩個指標相遇的結點一定是在環中。可以從這個結點出發,
*			一邊繼續向前移動一邊計數,當再次回到這個結點時就可以得到環中結點數了。

* 完成日期:2016-10-13
***************************************************************/ 

package org.marsguo.offerproject56;
	/*
	定義一個節點
	*/
class ListNode{
	int val;
	ListNode next;
	public ListNode(){
		
	}
	public ListNode(int val){
		this.val = val;
	}
	public String toString(){
		return val + "";
	}
}

class SolutionMethod1{
	/*
	找到帶環連結串列的入口節點函式
	@param head:頭節點
	*/
	public ListNode EntryFunction(ListNode head){
		if(head == null){
			return null;
		}
		
		ListNode p1 = head;				//設定兩個指標,使其期初都指向頭節點
		ListNode p2 = head;				//設定兩個指標,使其期初都指向頭節點
		
		/*
		circleNode1和circleNode2都指向環中任意一個節點,通過while迴圈,
		計算出環中所包含的節點數
		circleNode1先固定指向環中一個節點不變,circleNode2依次向後移動,直到
		circleNode1和circleNode2再次相遇,此時circleNode2所走過的節點數即為環中包含的節點數
		*/
		ListNode circleNode1 = CircleNodeFunction(head);			
		ListNode circleNode2 = CircleNodeFunction(head).next;
		int count = 1;				//用於計算環中節點數,從1開始計數
		
		while(circleNode1 != circleNode2){
			count++;
			circleNode2 = circleNode2.next;
		}
		System.out.println("環中節點數是: " + count);				//輸出環中的節點數
		/*
		使用 for迴圈讓p2先走count步,然後再使p1和p2以相同的速度在連結串列上向前移動
		直到他們相遇,則相遇的節點即為環的入口節點
		*/
		for(int i = 0; i < count;i++){
			if(p2.next != null){
				p2 = p2.next;
			}
		}
		
		while(p1 != p2){
			p1 = p1.next;
			p2 = p2.next;
		}
		
		return p1;			//返回環的入口節點
	}
	/*
	判斷環中節點數目,可用於判斷連結串列中是否存在環
	設定兩個指標,一個走的快,一個走的慢,如果兩個指標能夠相遇,則說明連結串列中存在環,
	並且相遇的節點即為環中的一個節點。
	*/
	public ListNode CircleNodeFunction(ListNode head){			//定義ListNode型函式
		if(head == null){
			return null;
		}
		ListNode pFast = head.next.next;
		ListNode pSlow = head.next;
		
		if(pSlow == null){
			return null;
		}
		
		while(pFast != null && pSlow != null){
			if(pFast == pSlow){
				return pFast;
			}
			pSlow = pSlow.next;
			pFast = pFast.next;
			
			if(pFast != null){
				pFast = pFast.next;		//使pFast走的速度比pSlow快,這樣兩個節點便會相遇
			}
		}
		return null;
	}
	
}

public class EntryNodeOfLoop {
	public static void main(String[] args){
		ListNode n1 = new ListNode(1);
		ListNode n2 = new ListNode(2);
		ListNode n3 = new ListNode(3);
		ListNode n4 = new ListNode(4);
		ListNode n5 = new ListNode(5);
		ListNode n6 = new ListNode(6);
		
		n1.next = n2;
		n2.next = n3;
		n3.next = n4;
		n4.next = n5;
		n5.next = n6;
		n6.next = n3;
		 
		SolutionMethod1 solution1 = new SolutionMethod1();
		System.out.println("連結串列中環的入口節點是:" + solution1.EntryFunction(n1));
		
		System.out.println();
	}
}

程式執行結果:

相關推薦

Offer試題56連結串列中環入口節點 Java實現

/************************************************************** * Copyright (c) 2016, * All rights reserved. * 版 本 號:v1.0

Offer 試題23連結串列中環入口節點 Java程式碼實現

題目描述 一個連結串列中包含環,請找出該連結串列的環的入口結點。   這題又用到了一快一慢兩個指標的方法,快指標一次走兩步慢指標一次走一步。可以證明,若存在環路,則這兩個指標一定會在環路中某個地方

offer試題7重建二叉樹(Java實現

題目:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。 思路:可以把二叉樹分為左右子樹分別構建,前序

offer試題12矩陣中的路徑(Java實現

題目:請設計一個函式,用來判斷在一個矩陣中是否存在一條包含某字串所有字元的路徑。路徑可以從矩陣中的任意一個格子開始,每一步可以在矩陣中向左,向右,向上,向下移動一個格子。如果一條路徑經過了矩陣中的某一個格子,則該路徑不能再進入該格子。 例如 a b c e s f c s a d e e 矩

offer--試題19二叉樹的映象--Java實現

題目描述: 請完成一個函式,輸入一個二叉樹,該函式輸出它的映象。 解題思路: 我們先前序遍歷這棵樹的每個結點,如果這個結點有子結點,就交換它的兩個子結點。當交換完所有非葉子結點的左右子結點後,就得到了樹的映象。 這裡採用了遞迴方式和非遞迴方式。

Offer學習】【試題56連結串列中環入口結點】

題目:一個連結串列中包含環,如何找出環的入口結點? 解題思路   可以用兩個指標來解決這個問題。先定義兩個指標P1和P2指向連結串列的頭結點。如果連結串列中環有n個結點,指標P1在連結串列上向前移動n步,然後兩個指標以相同的速度向前移動。當第二個指標

Offer.試題18.刪除連結串列中重複的節點

在一個排序的連結串列中,存在重複的結點,請刪除該連結串列中重複的結點,重複的結點不保留,返回連結串列頭指標。 例如,連結串列1->2->3->3->4->4->5 處理後為 1->2->5 思路: 設定三個指標。

Offer試題24 反轉連結串列

輸入一個連結串列,按連結串列值從尾到頭的順序返回一個ArrayList。 牛客網提交程式碼: /** * struct ListNode { * int val; * struct ListNode *next; * ListNode(int x)

offer——試題23鏈表中環入口節點

bre class aps spl tin try sin 一個 close 函數: 1 ListNode* MeetingNode(ListNode* pHead) 2 { 3 if(pHead==nullptr) 4 return n

offer試題30:包含min函式的棧(Java實現

題目:定義棧的資料結構,請在該型別中實現一個能夠得到棧的最小元素的min函式,在該棧中,呼叫min,push,及pop的時間複雜度都為O(1)。 直接上程式碼: import java.util.Stack; public class Solution {

offer試題59 對稱的二叉樹(java實現

解題思路: 可以定義一種遍歷演算法,先訪問根節點,再遍歷右子樹後遍歷左子樹,可以將這種遍歷方法稱為對稱的前序遍歷。現在可以通過比較二叉樹的前序遍歷序列和對稱前序遍歷序列來判斷二叉樹是否對稱。如果兩個序

試題56連結串列中環入口節點

      題目:一個連結串列中包含環,請找出該連結串列的環的入口結點。     這道題藉助於前面的連結串列的倒數第K個節點的思想,考慮快慢指標。考慮當知道了連結串列的環中所含的節點數目,用一個快指標

offer 試題57刪除連結串列中的重複節點 c++

本題有兩種 第一題:在一個排序的連結串列中,存在重複的結點,請刪除該連結串列中重複的結點,重複的結點不保留,返回連結串列頭指標。 例如,連結串列1->2->3->3->4->4->5 處理後為 1->2->3->4->5  

offer試題6從尾到頭列印連結串列Java實現

題目:輸入一個連結串列的頭結點,從尾到頭反過來打印出每個結點的值。 思路:因為要實現從頭到尾遍歷,然後從尾到頭列印,也就是說第一個遍歷到的最後一個列印,最後遍歷到的第一個列印,這很明顯符合棧 “先進後出” 的特點,所以我們可以利用棧來實現這種順序。 測試用例: 功能測試:

offer試題17-合併兩個排序連結串列

將兩個已經排好序的連結串列(升序)進行合併,使得合併後的連結串列仍然有序。 假設兩個連結串列分別為A和B,我的思路是將使用兩個指標p和q掃描兩個連結串列各一遍,將B連結串列中的元素插入到A中,最終形成一個新的連結串列。 邊界條件:(1)連結串列為空時;          

offer--試題16翻轉連結串列--Java實現

題目描述: 定義一個函式,輸入一個連結串列的頭結點,反轉該連結串列並輸出反轉後連結串列的頭結點。 解題思路: 為了反轉列表,其實就是為了改變next指標,由指向後一個變為指向前一個。 這裡為了避免連結串列斷裂,要儲存三個結點,即當前結點,前一個結點和後一

leetcode 240. 搜尋二維矩陣 II【陣列】【Medium】&&Offer試題4二維陣列中的查詢

題目: 編寫一個高效的演算法來搜尋 m x n 矩陣 matrix 中的一個目標值 target。該矩陣具有以下特性: 每行的元素從左到右升序排列。 每列的元素從上到下升序排列。 示例: 現有矩陣 matrix 如下: [

offer 試題50字元流中第一個只出現一次的字元

題目描述:請實現一個函式用來找出字元流中第一個只出現一次的字元。例如,當從字元流中只讀出前兩個字元"go"時,第一個只出現一次的字元是"g"。當從該字元流中讀出前六個字元“google"時,第一個只出現一次的字元是"l"。 解法: 使用雜湊表occurance[256] ;  初始化o

offer 試題19正則表示式匹配

請實現一個函式用來匹配包括'.'和'*'的正則表示式。模式中的字元'.'表示任意一個字元,而'*'表示它前面的字元可以出現任意次(包含0次)。 在本題中,匹配是指字串的所有字元匹配整個模式。例如,字串"aaa"與模式"a.a"和"ab*ac*a"匹配,但是與"aa.a"和"ab*a"均不匹配 c

offer 試題20表示數值的字串

請實現一個函式用來判斷字串是否表示數值(包括整數和小數)。例如,字串"+100","5e2","-123","3.1416"和"-1E-16"都表示數值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。 可以用A[.[B]][e|EC]或者.B[e|EC