成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

環形鏈表找入口,真的太妙了

開發 前端
鏈表是否有環問題看似簡單,但實際處理上有很多需要注意的,這個問題是非常高頻筆試面試題,記憶不牢固容易遺忘,可以認真看看學習一波!當然今天這兩題對應力扣141和力扣142,有個小伙伴就在某手面試中遇到了。

[[402783]]

本文轉載自微信公眾號「bigsai」,作者bigsai。轉載本文請聯系bigsai公眾號。

鏈表是否有環問題看似簡單,但實際處理上有很多需要注意的,這個問題是非常高頻筆試面試題,記憶不牢固容易遺忘,可以認真看看學習一波!當然今天這兩題對應力扣141和力扣142,有個小伙伴就在某手面試中遇到了。

判斷鏈表是否有環

問題描述:

給定一個鏈表,判斷鏈表中是否有環。

如果鏈表中有某個節點,可以通過連續跟蹤 next 指針再次到達,則鏈表中存在環。

如果鏈表中存在環,則返回 true 。否則,返回 false 。

你能用 O(1)(即,常量)內存解決此問題嗎?

分析:

對于這個問題,如果沒有內存空間的限制,首先想到的就是使用哈希的方法,用一個哈希存儲節點,然后向下枚舉鏈表節點:

如果發現其中有在哈希中,那么就說明有環返回true。

如果枚舉到最后結束,那就說明沒有環

但是這樣并不滿足O(1)空間復雜度的要求,我們應該怎么處理呢?

如果鏈表尾部有環,如果一個節點枚舉到后面會在閉環中不斷循環枚舉,那么怎么樣能高效判斷有環并且能快速終止呢?

有環,其實就是第二次、第三次走過這條路才能說它有環,一個指針在不借助太多空間存儲狀態下無法有效判斷是否有環(有可能鏈表很長、有可能已經在循環了),咱們可以借助 快慢指針(雙指針) 啊。

其核心思想就是利用兩個指針:快指針(fast)和慢指針(slow),它們兩個同時從鏈表頭遍歷鏈表,只不過兩者速度不同,如果存在環那么最終會在循環鏈表中相遇。

我們在具體實現的時候,可以快指針(fast)每次走兩步,慢指針(slow)每次走一步。如果存在環的話快指針先進入環,慢指針后入環,在慢指針到達末尾前快指針會追上慢指針。

快慢指針如果有相遇那就說明有環,如果快指針先為null那就說明沒環。

具體實現代碼為:

  1. /** 
  2.  * Definition for singly-linked list. 
  3.  * class ListNode { 
  4.  *     int val; 
  5.  *     ListNode next
  6.  *     ListNode(int x) { 
  7.  *         val = x; 
  8.  *         next = null
  9.  *     } 
  10.  * } 
  11.  */ 
  12. public class Solution { 
  13.     public boolean hasCycle(ListNode head) { 
  14.         ListNode fast=head; 
  15.         ListNode slow=fast; 
  16.         while (fast!=null&&fast.next!=null) { 
  17.             slow=slow.next
  18.             fast=fast.next.next
  19.             if(fast==slow) 
  20.                 return true
  21.         } 
  22.         return false;     
  23.     } 

提高:找到環的入口

給定一個鏈表,返回鏈表開始入環的第一個節點。如果鏈表無環,則返回 null。

為了表示給定鏈表中的環,我們使用整數 pos 來表示鏈表尾連接到鏈表中的位置(索引從 0 開始)。如果 pos 是 -1,則在該鏈表中沒有環。注意,pos 僅僅是用于標識環的情況,并不會作為參數傳遞到函數中。

說明:不允許修改給定的鏈表。

你是否可以使用 O(1) 空間解決此題?

這題相比上一題又難了一些,因為如果鏈表成環,需要找到入口。

分析:

如果不考慮內存使用,我肯定還會首先考慮哈希,將節點存著然后如果出現第二次則說明有環并直接返回,實現的代碼也很簡單,走投無路可以用這個方法:

  1. /** 
  2.  * Definition for singly-linked list. 
  3.  * class ListNode { 
  4.  *     int val; 
  5.  *     ListNode next
  6.  *     ListNode(int x) { 
  7.  *         val = x; 
  8.  *         next = null
  9.  *     } 
  10.  * } 
  11.  */ 
  12. public class Solution { 
  13.     public ListNode detectCycle(ListNode head) { 
  14.         int pos=-1; 
  15.         Map<ListNode,Integer>map=new HashMap<ListNode, Integer>(); 
  16.         ListNode team=head; 
  17.         while (team!=null
  18.         { 
  19.             if(map.containsKey(team)){ 
  20.                 pos=map.get(team); 
  21.                 return team; 
  22.             } 
  23.             else  
  24.                 map.put(team,++pos); 
  25.             team=team.next
  26.         } 
  27.         return null
  28.     } 

但是怎么使用O(1)的空間復雜度完成這個操作呢?上面一題的思路是使用快慢指針判斷是否有環,但是怎么鎖定環的入口呢?

這個題看起來是個算法題,實際上是個數學推理題。這題的關鍵也是快慢指針,不過需要挖掘更多的細節 。

回憶一下快慢指針能夠挖掘的細節:

知道慢指針走了x步,快指針走了2x步,但是僅僅知道這兩個條件還推導不出什么東西,我們能夠進行的操作也只有用O(1)的方法進行一些操作。不過這里面快慢指針和前面有點不同的是我們前面用一個頭結點開始計數。

我們還可以進行什么操作?

既然知道相遇的這個點在環內,那么我們可以用一個新的節點去枚舉一圈看看環的長度是多少哇!

這里面,我們可以知道fast走的步數2x,slow走的步數x,以及環長y。

我們知道,慢指針是第一次入環,但快指針可能已經走了好幾圈,但是多走的步數一定是環的整數倍(不然不可能在同一個位置相遇)。

那么可以得到 快指針步數=慢指針步數+n圈環長度。當然這里n我暫時不知道是多少。換算成公式,那就是 2x=x+ny 消去一個x得到:x=ny。

上面的圖我也標注快指針多走的是整數圈數。難點就在這里,需要變通:

快指針多走的x是環長y的整數倍n,慢指針走的x也是環長y的整數倍n。

那么這樣有什么用呢?

如果某個節點從起點出發,走到fast,slow交匯點走的是x步(n*y步)。此時,如果某個指針從fast,slow交匯點開始如果走環長的整數倍,那么它到時候還會在原位置。

也就是說從開始head節點team1走x步,從fast,slow交匯節點team2走x步,它們最終依然到達fast,slow交匯的節點,但是在枚舉的途中,一旦team1節點遍歷的到環內,那么就和team2節點重合了,所以它們一旦相等那就是第一個交匯的點了。

具體實現依然要判斷是否有環,實現代碼為:

  1. /** 
  2.  * Definition for singly-linked list. 
  3.  * class ListNode { 
  4.  *     int val; 
  5.  *     ListNode next
  6.  *     ListNode(int x) { 
  7.  *         val = x; 
  8.  *         next = null
  9.  *     } 
  10.  * } 
  11.  */ 
  12. public class Solution { 
  13.     public ListNode detectCycle(ListNode head) { 
  14.         boolean isloop=false
  15.         ListNode fast=new ListNode(0);//頭指針 
  16.         ListNode slow=fast; 
  17.         fast.next=head; 
  18.         if(fast.next==null||fast.next.next==null
  19.             return null
  20.         while (fast!=null&&fast.next!=null) { 
  21.             fast=fast.next.next
  22.             slow=slow.next
  23.             if(fast==slow) 
  24.             { 
  25.                 isloop=true
  26.                 break; 
  27.             } 
  28.         } 
  29.         if(!isloop)//如果沒有環返回 
  30.             return null
  31.         ListNode team=new ListNode(-1);//頭指針 下一個才是head 
  32.         team.next=head; 
  33.         while (team!=fast) { 
  34.             team=team.next
  35.             fast=fast.next
  36.         } 
  37.         return team; 
  38.     } 

總結

到此,這個問題就介紹到這里,如果有想法歡迎留言,后面會繼續分享更多數據結構與算法介紹以及重要題型,歡迎mark。

 

責任編輯:武曉燕 來源: bigsai
相關推薦

2023-11-27 16:26:20

mainC語言

2021-03-11 08:53:20

Java數據結構算法

2021-12-21 08:19:29

數據結構算法鏈表相交

2023-04-17 07:33:11

反轉鏈表移除鏈表

2025-05-06 07:00:00

Python鏈表

2023-07-27 07:28:04

存儲鏈表HashSet

2017-08-07 15:18:18

創新

2017-07-04 17:09:10

Map環形緩沖區數據

2012-02-02 10:18:01

API

2012-04-19 23:56:26

蘋果

2015-03-06 09:47:53

小米變化

2021-06-08 10:23:12

人工智能人臉識別Deepfake

2021-08-18 15:23:42

SDNSD-WAN軟件定義網絡

2010-08-25 15:14:35

飯碗

2023-03-15 09:00:43

SwiftUISlider

2012-07-20 15:17:19

移動購物

2023-10-10 19:32:43

強靜態類型制表符

2020-10-21 10:53:33

Google壟斷法瀏覽器

2019-08-27 08:24:17

簡歷技能工作

2020-12-24 06:00:27

Python編程語言開發
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 性一交一乱一透一a级 | 欧美久久一区二区三区 | 啪啪av| 国产免费一区二区三区 | 欧美极品少妇xxxxⅹ免费视频 | 国产精品区二区三区日本 | 日本三级做a全过程在线观看 | 欧美日韩中文字幕 | 成年人国产在线观看 | 欧美在线日韩 | 精品综合| 久久tv在线观看 | 在线成人福利 | 久久国产婷婷国产香蕉 | 射久久 | 国产精品久久久乱弄 | 免费黄色片在线观看 | 日韩欧美一级片 | 日韩欧美在线不卡 | 91亚洲欧美 | 免费高清av| 亚洲三级在线观看 | 国产一区二区在线视频 | 一区二区三区四区五区在线视频 | 美女爽到呻吟久久久久 | 这里只有精品999 | 亚洲高清免费观看 | 久久精品欧美电影 | 亚洲精品久久久久久宅男 | 九九热精品视频 | 亚洲a在线观看 | 国产在线1| 国产精品福利网站 | 精品欧美一区免费观看α√ | 黄视频国产 | 国产色视频网站 | 黄色片在线观看网址 | 狠狠躁天天躁夜夜躁婷婷老牛影视 | 日韩成人在线观看 | 欧美成人a | 8x国产精品视频一区二区 |