1. 程式人生 > >如何判斷一個單鏈表是否有環以及環入口

如何判斷一個單鏈表是否有環以及環入口

這是一個在我們學習資料結構的時候經常會遇到的問題,今天給大家帶來這個問題的幾種解法。

方法一

最容易想到的辦法就是遍歷單鏈表,如果單鏈表有環的話那麼會進入死迴圈,但是我們不知道單鏈表的長度,所以如果單鏈表長度很長,我們一直向下遍歷,也無法分辨出是單鏈表還沒遍歷完還是進入了死迴圈。

所以這種解法不靠譜。

方法二

我們可以在遍歷單鏈表中的每個元素的時候,每遍歷一個新的節點,就從頭再開始遍歷一次已經遍歷過的節點,用新節點和之前遍歷過的節點相比較,如果新節點之前遍歷過的節點相同,就說明單鏈表有環。

單鏈表

比如說已存在的單鏈表:A->B->C->D->E->F->G->D,在遍歷到第七個節點(D)的時候,再在從頭節點開始遍歷到第三個節點,因為第三個集結點(D)和第七個節點相同,所以單鏈表一定有環。

假設從單鏈表頭節點到環入口節點的距離是D,單鏈表的環長是S。那麼演算法的時間複雜度是0+1+2+3+….+(D+S-1) = (D+S-1)*(D+S)/2,可以理解成O(N*N)。

演算法沒有建立額外儲存空間,空間複雜度可以簡單地理解成為O(1)。

所以這個演算法的時間複雜度是O(N*N),空間複雜度是O(1)。

找環入口的話就很簡單了,遍歷到第一個判定單鏈表有環的節點(D)就是環的入口。

方法三

考慮到方法二每遍歷一個新節點的時候都需要從頭開始遍歷遍歷一遍節點,會導致時間複雜度很高,所以我們可以把已經遍歷過的節點用一個HashSet存起來,然後每遍歷一個新節點的時候再去和HashSet中的元素做匹配,如果HashSet中已存在該節點,那麼單鏈表有環。

假設從單鏈表頭節點到環入口節點的距離是D,單鏈表的環長是S。而每一次HashSet查詢元素的時間複雜度是O(1),所以總體的時間複雜度是1*(D+S)=D+S,可以簡單理解為O(N)。

而演算法的空間複雜度還是D+S-1,可以簡單地理解成O(N)。

這個演算法的時間複雜度是O(N),空間複雜度是o(N).

找環入口和方法二一樣,遍歷到第一個判定單鏈表有環的節點(D)就是環的入口。

方法四

還有一種思路是建立兩個變數slow和fast同時指向頭節點,然後slow每次向後遍歷一個節點,fast每次向後遍歷兩個節點,如果單鏈表沒有環的話那麼slow將永遠追不上fast,而如果單鏈表有環的話slow就會追上fast。

單鏈表2

下面我們來模擬隨著單鏈表的遍歷slow和fast兩個變數值的變化:

次數\變數 slow fast
0 A A
1 B C
2 C E
3 D G
4 E E
5 F G
6 G E
7 D G
8 E E

單鏈表3

可以看到遍歷到第八次的時候,slow追上了fast,所以單鏈表有環。

假設從單鏈表頭節點到環入口節點的距離是D,單鏈表的環長是S。那麼迴圈會進行S*K次,K為正整數,可以簡單理解為O(N)。除了兩個指標以外,沒有使用任何額外儲存空間,所以空間複雜度是O(1)。

這個演算法的時間複雜地是O(N),空間複雜度O(1)。

那麼如何找到環的入口呢?下面我們來進行一個小小的數學計算:設從單鏈表頭節點到環入口節點的距離是D,環入口到相交點的距離是X,設slow和fast第一次相遇時fast走了n圈環,slow走的距離為len,那麼fast走的距離是2*len,可以得出下面的兩個等式:

len = D + X
2 * len = D + X + n * R

兩個等式相減可以的到:len = n * R - X

通過這個等式我們可以再定義兩個變數out和in,out指向單鏈表頭節點,in指向之前slow和fast第一次相交的節點,out和in同時向後遍歷,第一次相交的點就是環的入口。

單鏈表4

下面我們來模擬隨著單鏈表的遍歷out和in兩個變數值的變化:

次數\變數 out in
0 A E
1 B F
2 C G
3 D D

可以看到遍歷到第三次的時候,out和in相遇在D節點,所以D節點時單鏈表的環入口。

今天關於單鏈表是否有環以及環入口的問題就分享到這裡了,提供了四種解法,第一種解法不太友好也不太合理,第二中解法時間複雜度太高,第三種解法空間複雜度太高,第四種解法可能時目前的最優解法了,希望對大家有所幫助。

喜歡這篇文章的朋友,歡迎長按下圖關注公眾號lebronchen,第一時間收到更新內容。
掃碼關注

相關推薦

如何判斷一個單鏈是否以及入口

這是一個在我們學習資料結構的時候經常會遇到的問題,今天給大家帶來這個問題的幾種解法。 方法一 最容易想到的辦法就是遍歷單鏈表,如果單鏈表有環的話那麼會進入死迴圈,但是我們不知道單鏈表的長度,所以如果單鏈表長度很長,我們一直向下遍歷,也無法分辨出是單鏈表還

如何判斷一個單鏈是否

算法 查找 public class LinkedListRing{ static class LinkedNode<T>{ private T t ; private LinkedNode<T> next = null; public LinkedNode(T t)

演算法之(二)判斷一個單鏈是否

思路:如果一個單鏈表中有環,用一個指標去遍歷,永遠不會結束,所以可以用兩個指標,一個指標一次走一步,另一個指標一次走兩步,如果存在環,則這兩個指標會在環內相遇,時間複雜度為O(n)。 拓展問題1:如果單鏈表有環,找出環的入口節點(環的連線點)。 這裡先證明一個

筆試題:判斷一個單鏈是否,如果,找出的起始位置

</pre><pre name="code" class="cpp">Node * FindLoop(Node *phead) { Node *p = phead,q = phead,h = phead; while(p && q->next)

判斷一個單鏈是否

主函式中沒有出現具體的連結串列,主要看判斷有無環函式ExitLoop. 外函式的while迴圈條件的判定:如果fast指標指向NULL,if條件語句不成立,返回flag=0:不存在環。 如果flag走到最後一個結點時,要是不給定一個條件,while繼續執行,flag一次迴圈

關於連結串列的面試問題(判斷一個單鏈中是否

判斷一個單鏈表中是否有環  首先連結串列結點宣告如下: struct ListNode { int key; ListNode * next; }; 思路:如果一個單鏈表中有環,用一個指標去遍歷,永遠不會結束,所以可以用兩個指標,一個指標一次走一步,另

判斷一個單鏈是否帶,並求出的長度,及入口

單鏈表是否帶環? 用快慢指標分別遍歷這個單鏈表,如果快慢指標能相遇,就代表有環的存在。 環的長度? 當快慢指標相遇時,記錄當前位置,然後走一圈的長度就是環的長度。 環的入口點? 設快指標F走兩個結點,慢指標S走一個結點。 F=2*S;     &nb

演算法題010 -- [判斷一個單鏈是否是迴文連結串列] by java

題目 判斷一個單鏈表是否是迴文連結串列。 如:[1, 2, 3, 2, 1] 就是一個迴文連結串列,正著依次看連結串列中元素和反著依次看連結串列中元素都是一樣的。 要求: 時間複雜度 O(n) 空間複雜度 O(1) 程式碼 package algorithm01

判斷一個單鏈是否是迴文連結串列

思路有三種: 1.用棧順著連結串列儲存所有元素,然後依次出棧從頭再比較。時間複雜度O(N),空間複雜讀O(N)。 2.還是棧,不過只儲存前一半元素,然後和後一半對比即可。時間複雜度O(N),空間複雜

迴圈連結串列的特性以及判斷單鏈是否(九)

typedef struct CLinkList { int data; struct CLinkList* next; }node; typedef struct CLinkList* LinkList; int compareStep(LinkList L) { LinkList cur1 = L;

11.判斷單鏈是否

兩個指針 next 測試 重載 else reader sta clas 復雜度 判斷單鏈表是否有環: 這裏也是用到兩個指針,如果一個鏈表有環,那麽用一個指針去遍歷,是永遠走不到頭的。 因此,我們用兩個指針去遍歷:first指針每次走一步,second指針每次走兩步

判斷單鏈是否

plc .html weibo app sin pla mpc html cnblogs 辜鈉魯u0ri0忌蠱負http://huiyi.docin.com/txqq_8fb449e9c9儼夾銥43gi1鑰倚蚜http://www.docin.com/app/user/us

JS-單鏈是否以及的入點問題

給定一個連結串列,判斷連結串列中是否有環。 進階: 你能否不使用額外空間解決此題? 方案1 雜湊表 雜湊表是最容易理解的一個方案 建立一個雜湊表,如果不存在就向雜湊表中新增資料,存在的話就直接返回true(存在的可能只有P點,同時P點也是環的入點(這個和下一道題

判斷單鏈是否,如果找出入口位置=>求兩個相交連結串列的交點

首先如何判斷一個連結串列是否有環: 設定兩個指標(fast, slow),初始值都指向頭,slow每次前進一步,fast每次前進二步,如果連結串列存在環,則fast必定先進入環,而slow後進入環,兩個指標必定相遇。(當然,fast先行頭到尾部為NULL,則為無環連結串列

Java演算法:判斷單鏈是否

README 單鏈表是否有環,這是一個挺有意思的問題,這裡我並沒有提出新的解法,而是解釋了現有的解法,幫助新人和自己理解。 題目描述 判斷一個單鏈表是否有環,如果有,返回第一個環內的節點的引用,如果沒有環,返回nuill。 程式設

單鏈是否的長度,以及的起始點

尋找倒數第k個結點 public void lastk(int k){ Entry cur1=head; Entry cur2=head; if(k<0||k>getlength()){

Java判斷單鏈是否的兩種實現方法

http://blog.jobbole.com/106227/ 方法一:首先從頭節點開始,依次遍歷單鏈表的每一個節點。每遍歷到一個新節點,就從頭節點重新遍歷新節點之前的所有節點,用新節點ID和此節點之前所有節點ID依次作比較。如果發現新節點之前的所有節點當中存

題目:程式碼實現判斷單鏈是否

#include "stdio.h" #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define MAXSIZE 20 /* 儲存空間初始分配量 */ typedef int Status;/* Status是函式的型別,其值

判斷單鏈是否,並找出入口【python】

問題: 1、如何判斷一個連結串列是不是這類連結串列? 2、如果連結串列為存在環,如果找到環的入口點? 一、判斷連結串列是否存在環,辦法為: 設定兩個指標(fast, slow),初始值都指向頭,slow每次前進一步,fast每次前進二步,如果連結串列存在環,則fast必定先進入環,而slow後進入環

如何判斷單鏈是否入口的長度和總長

問題描述 1.如何判斷單鏈表是否有環? 2.如果有環,求出環的入口 3.求環長 4.求總長 探討 要想判斷有環,我們可以聯絡實際生活中的例子,很容易就想到操場上跑圈,因為是環形,所以快的肯定會追上慢的,所以我們可以應用到連結串列上,用一個快