【劍指offer中等部分23】連結串列中環的入口結點(java)
阿新 • • 發佈:2020-12-25
一、題目描述
給一個連結串列,若其中包含環,請找出該連結串列的環的入口結點,否則,輸出null。
二、分析
方法一
找到環的入口結點,就是找到剛進入環的第一個結點,如下圖,找入口結點就是找第一個發生重複的結點,那麼我們又可以借鑑之前兩個習題(中等20、中等22)的思想,也就是用一個List集合,如果集合中不包含結點,就新增。如果集合中包含結點,那麼就跳出迴圈,返回該結點,該目標結點即為第一個重複的結點,也就是入口結點,由於要遍歷整個連結串列,故其時間複雜度為O(n2)。
實現程式碼如下:
import java.util.List;
import java.util.ArrayList;
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
ListNode targetNode = null;
if(pHead == null || pHead.next ==null){
return null;
}
List<ListNode> list = new ArrayList<ListNode>(); //集合中存放結點
list.add(pHead); //新增頭結點
targetNode = pHead.next;
// 判斷是否存在環,即list中是否存在重複結點
while(!list.contains(targetNode)){
list.add(targetNode);
targetNode = targetNode.next;
}
return targetNode;
}
}
方法二
快慢指標(需要理解,但這個演算法時間複雜度更低)
方法分兩個步驟處理
2、fast繼續指向這個相遇點,但是讓low指標指向連結串列頭結點,此時快慢指標都一起每次走一步,最終他們會在入口結點相遇。
為什麼這樣會在入口結點相遇呢?我們帶著這個問題進行推理分析一下,如下圖
a,b,c分別為三個結點之間的距離
我們先討論到相遇點,fast與low兩指標走過的路程:
快指標路程 = a+(b+c)k+b ,k≥1,這表示至少一圈環,b+c為一個環的長度
慢指標路程 = a+b
由於快指標步長等於慢指標2倍,則
a+(b+c)k+b = 2(a+b),化簡得a = (k-1)(b+c)+c,該式子意思是:
連結串列頭到入口結點的距離 = 相遇點到入口結點的距離+(k-1)圈環長度
因此,在找到相遇點後,還需要將low重置到表頭,繼續每次走一步,這樣得話,兩個最後一定會在入口結點相遇,返回該結點即可
實現程式碼如下:
import java.util.List;
import java.util.ArrayList;
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
if(pHead == null|| pHead == null)
return null;
ListNode fast = pHead;
ListNode low = pHead;
//找相遇點
while(fast != null && fast.next != null){
fast = fast.next.next;
low = low.next;
if(fast == low)
break;
}
//相遇點非空
if(fast == null|| fast.next == null)
return null;
low = pHead; //連結串列頭出發
while(fast != low){
fast = fast.next;
low = low.next;
}
return low;
}
}