[程式設計題] nk 連結串列中的入環節點-快慢指標和雜湊方法
阿新 • • 發佈:2020-07-22
[程式設計題] nk:連結串列中的入環節點
題目描述
輸入輸出例子
無
思路
方法1、藉助雜湊表
思想:我們通過一個dummyNode不斷遍歷每一個節點,當我們每次遍歷到這個當前節點的時候就看他在不在雜湊表中,不在的話加入進去;在的時候就恰好這個節點就是入環節點。
時間複雜度:O(n)
Java程式碼
import java.util.*; /* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } */ public class Solution { //方法1:藉助雜湊表; //思想:每次遍歷一個節點,就放入到雜湊表,如果再次發現雜湊表中有這個節點的時候就是環的入口 public ListNode EntryNodeOfLoop(ListNode pHead){ //跑龍套節點 ListNode dummyNode = pHead; //雜湊表 HashSet<ListNode> hashSet = new HashSet<ListNode>(); while(dummyNode!=null){ if(hashSet.contains(dummyNode)){ return dummyNode; //找到入環點 } hashSet.add(dummyNode); //否則放入雜湊表 dummyNode = dummyNode.next; } //退出迴圈,即為找到入環點,無環 return null; } }
輸出的效率:
方法2:快慢指標
思想:
總結思想:
- 第一趟跑的時候找相遇點(定義fast=phead.next; slow = phead;錯開的好)
- 找到相遇點計算環長
- 重新定義快慢指標指向,pFast指向phead,pSlow指向pHead後的環長n的位置;同時以step=1走
- 相遇即返回該節點為入環點。
時間複雜度O(n)
Java程式碼
//方法2:快慢指標(第一次快慢速度2:1找到相遇點,計算環長,第二次同步速度走,在入環點相遇) public ListNode EntryNodeOfLoop(ListNode pHead){ //需要考慮只有一個節點的邊界情況 if(pHead==null) {return null;} //快慢指標 ListNode pFast = pHead.next; //注意一開始讓快慢指標錯開,因為不錯開的話,在第一次相遇點的邏輯中直接if比較返回相等。返回的就是首節點相遇 ListNode pSlow = pHead; //標註是否有環 boolean isCircle = false; //計算環長的計數器 int count=1; //1 第一次走找是否有環和相遇點 while(pFast!=null && pFast.next!=null){ if(pFast==pSlow){ //在初始快慢指標賦值的時候讓錯開,不然在這裡會返回首節點相遇的 isCircle = true; break;//一定記得有環了跳出while } //否則快指標2倍速走,慢指標1倍速走 pFast = pFast.next.next; pSlow = pSlow.next; } //2 檢測isCircle欄位看是否有環,有環的話就計算環長 if(!isCircle){ return null;//無環 }else{//有環 //2.1 讓快指標從相遇點再繞環走一圈,計算環長 pFast = pFast.next; while(pFast!= pSlow){ count++; //這裡while內用的dummyFast.next,故計算的count還差最後一步。 pFast = pFast.next; } } //3 我們得出了環長count值,重新把指標重新指向,快慢指標以step=1開始走,相遇就是入環點 pFast = pSlow = pHead; //退出while後就是找到slow應該指向的節點的地方 while(count>0){ pSlow = pSlow.next; count--; } while(pFast!=pSlow){ pFast = pFast.next; pSlow = pSlow.next; } //退出while,返回的節點就是相遇點 return pFast; }
時間複雜度 :O(n)
輸出: