劍指 offer之鏈表中環的入口結點_Java

題目:鏈表中環的入口結點
題目描述
給一個鏈表,若其中包含環,請找出該鏈表的環的入口結點,否則,輸出null。

解題思路:
ps: 來自劍指 offer評論區
在這裏插入圖片描述

假設x爲環前面的路程(黑色路程),a爲環入口到相遇點的路程(藍色路程,假設順時針走), c爲環的長度(藍色+橙色路程)
當快慢指針相遇的時候:
此時慢指針走的路程爲Sslow = x + m * c + a
快指針走的路程爲Sfast = x + n * c + a
2 Sslow = Sfast
2 * ( x + m*c + a ) = (x + n *c + a)
從而可以推導出:
x = (n - 2 * m )*c - a
= (n - 2 *m -1 )*c + c - a
即環前面的路程 = 數個環的長度(爲可能爲0) + c - a
什麼是c - a?這是相遇點後,環後面部分的路程。(橙色路程)
所以,我們可以讓一個指針從起點A開始走,讓一個指針從相遇點B開始繼續往後走,
2個指針速度一樣,那麼,當從原點的指針走到環入口點的時候(此時剛好走了x)
從相遇點開始走的那個指針也一定剛好到達環入口點。
所以2者會相遇,且恰好相遇在環的入口點。
最後,判斷是否有環,且找環的算法複雜度爲:
時間複雜度:O(n)
空間複雜度:O(1)

代碼實現:

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/

public class Solution {
    public ListNode EntryNodeOfLoop(ListNode pHead){
        //定義兩個快慢指針
		ListNode slow=pHead;
		ListNode fast=pHead;
		//快指針一次走兩步,滿指針一次走一步,找到兩個鏈表的相遇節點
		while(fast!=null && fast.next!=null) {
			slow=slow.next;
			fast=fast.next.next;
			//兩者的相遇點
			if(slow==fast) {
				//使快慢指針中的其中一個頭節點
				fast=pHead;
				//找到換的入口節點
				while(slow!=pHead) {
					slow=slow.next;
					pHead=pHead.next;
				}
				return slow;
			}
		}
		//沒有相遇節點,即沒有環,返回null
		return null;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章