1. 程式人生 > >判斷連結串列中是否有環的三種思路

判斷連結串列中是否有環的三種思路

連結串列在面試中出現的頻率很高,有的比較正常,考連結串列的常規操作,主要看基本功是否紮實,有些就比較難,難在思維的改變和是否能夠想到對應的點。這裡出現的是其中一個題目,我稱之為有環連結串列問題。也就是從判斷一個單鏈表是否存在迴圈而擴充套件衍生的問題。下面來看問題如何解決。

首先來看最基本的這個問題:如何判斷一個單鏈表是否存在迴圈,連結串列數目未知。演算法不能破壞連結串列。

這裡我們可以想到有三種解決的方法。

第一種方法,將所有的遍歷過的節點用某個結構儲存起來,然後每遍歷一個節點,都在這個結構中查詢是否遍歷過,如果找到有重複,則說明該連結串列存在迴圈;如果直到遍歷結束,則說明連結串列不存在迴圈。

這個結構我們可以使用hash來做,hash中儲存的值為節點的記憶體地址,這樣查詢的操作所需時間為O(1),遍歷操作需要O(n),hash表的儲存空間需要額外的O(n)。所以整個演算法的時間複雜度為O(n),空間複雜度為O(n)。

第二種方法,比較的特別,是使用反轉指標的方法,每過一個節點就把該節點的指標反向。

當有環的時候,最後指標會定位到連結串列的頭部,如果到最後,都沒有再到頭部,那說明連結串列不存在迴圈。

這個方法會破壞掉連結串列,所以如果要求是不能破壞連結串列的話,我們最後就還需要反轉一下,再將連結串列恢復。

這個方法使用的空間複雜度為O(1),其實是使用了3個指標,用於進行反轉。同時,時間複雜度為O(n)。

第三種方法,可能大家已經知道了,同時也是面試官大多想要得到的答案,就是快慢指標

快指標pf(f就是fast的縮寫)每次移動2個節點,慢指標ps(s為slow的縮寫)每次移動1個節點,如果快指標能夠追上慢指標,那就說明其中有一個環,否則不存在環。

這個方法的時間複雜度為O(n),空間複雜度為O(1),實際使用兩個指標。