這應該是乙個比較老的題目,在一次面試的過程中碰到過該題目,並沒有能夠給出最佳的答案。當時面試時沒有其他條件的限制,卻只能給出了幾乎是最差的答案;當看到這個命題一步一步的限制的時候,我也只能給出第三步的答案。
昨天有幸又翻到了這個題目,自己順手做做,居然仍然沒有太多的進步,最佳答案的思路在腦海裡面已經不復存在,今天就拿這個題目溫習一下,有興趣的人也可以一步一步的思考下去看看。(在《程式設計之美》中也是有些題目不能給出最佳答案,甚至看到答案後過些日子就忘記了思路。)
題目:怎樣才能檢測到鍊錶中存在迴圈?
通常的第一種答案:對鍊錶的訪問的每個元素做個標記(修改鍊錶資料結構,增加乙個標識),遍歷鍊錶,如果遇到已經標記過的元素,則說明鍊錶存在迴圈。
注:這應該是最簡單的方案,也是在具體實現中可能採用最多的方案;雖然對每個元素增加了標識,但卻是時間複雜度最低的一種方案,只需遍歷一遍!然而不幸的是,我在第一次面試的時候,卻沒有想到這個方案,雖然在實際中早就類似的方式改寫過別人的**。
第二個限制:鍊錶位於唯讀區域(無法做標記)
通常第二種答案:建立乙個動態陣列,訪問每個元素,然後儲存在陣列中。檢查每乙個後續的元素,然後從頭查詢這個陣列,檢查是否存在陣列中。(書上給的答案說一些可憐的程式設計師會糾纏如何用雜湊表來優化陣列訪問的細節之中,結果在這裡卡了殼。) 注
1:幸運的是,我不是那些可憐的程式設計師,我在面試中直接給出了這個答案。但是這個答案遠遠不能令我滿意,在實時應用中,這樣的查詢往往是災難性的!每乙個元素的的遍歷是
1~n的搜尋過程,不是
cpu就是程式設計師會**! 注
2:遠遠不滿意自己的答案,有沒有更好的辦法解決這個問題呢?改變檢索過程,會不會大大縮短每個元素的
1~n的遍歷過程,有可能,那就是雜湊表!試著建立乙個雜湊演算法與一張雜湊表,或者是二次雜湊表:每次檢索時先計算雜湊值,然後看看該值是否在雜湊表中,如果在,那麼就比較數值是否一直(甚至再次雜湊,然後再比較),否則就可以檢視下個鍊錶元素。(這可能是乙個好的解決方案,速度上應該有很大的提高。但高效雜湊演算法的實現,依賴於鍊錶資料的特徵;另外,不幸的是,這只是我的猜測,我沒有寫過這樣的程式)
第三個限制:記憶體非常有限哦!(但假定了如果出現迴圈,肯定出現在前n項中)
通常第三種答案:只建立乙個指標,指向鍊錶頭部!每次遍歷鍊錶的乙個元素,就從該指標指向的鍊錶頭部比較一遍,知道第
n個元素!
注:在書中對該提問給出的提示是:如果程式設計師能走到這一步。幸運的是,好像如果有限制的時候,我也能差不多給出這個答案。但是演算法實現乏善可陳,效率極其低下!
第四個限制:記憶體就是非常有限!而且鍊錶足夠長,迴圈可能出現在任何地方!
最後答案:無!除了照抄上面的答案,我實在想不出任何的其他的答案!我腦海裡只剩下乙個線索:存在迴圈的元素可能記憶體位址相同。但我沒有辦法使用這個條件。
注:幸運的是,書中對該提問給出的提示是:即使優秀的候選者也會在這裡碰壁!還好,自己還不算是太爛!當然我留給自己的最後乙個線索,實際上並沒有太多的用途,只是用來做了最後的判據而已!
癥結:的鍊錶中存在迴圈的最重要特徵是什麼?是一旦進入迴圈永遠都跳不出這個迴圈!永遠!
我應該設法記住這個答案,也是寫本文的目的。
書中給出的答案:設定兩個指標p1,
p2。 1.
排除乙個特殊情況,就是只有三個元素(實際上只有兩個),第二個元素的
next
是第乙個元素!
p1指向第乙個元素,p1的
next
為第二個元素,p1的
next
的next
原色為第三個元素。令
p2指向第三個元素,看看他們相等與否? 2.
如果不等,把
p1指向p1的
next
元素(後移乙個元素);
p2指向
next
的next
元素(後移兩個元素)。如果存在迴圈,那麼
p2先進入迴圈並再也不會出來,而後
p1進入迴圈,周而復始,其中乙個指標終會追上另外乙個,出現
p1==p2
的情況,則存在迴圈!否則,
p2首先出現
null
,則說明該鍊錶不存在迴圈。
評:雖然該方法可能要在存在的迴圈的煉表裡兜
n個圈子,然後才能檢測出來!但是時間複雜度仍然僅次於第一種方式!可是別忘記,他的空間複雜度為
0!其他可是都是n!
怎樣檢測鍊錶中存在迴圈?
這應該是乙個比較老的題目,在一次面試的過程中碰到過該題目,並沒有能夠給出最佳的答案。當時面試時沒有其他條件的限制,卻只能給出了幾乎是最差的答案 當看到這個命題一步一步的限制的時候,我也只能給出第三步的答案。昨天有幸又翻到了這個題目,自己順手做做,居然仍然沒有太多的進步,最佳答案的思路在腦海裡面已經不...
怎樣檢測鍊錶中存在迴圈?
這應該是乙個比較老的題目,在一次面試的過程中碰到過該題目,並沒有能夠給出最佳的答案。當時面試時沒有其他條件的限制,卻只能給出了幾乎是最差的答案 當看到這個命題一步一步的限制的時候,我也只能給出第三步的答案。昨天有幸又翻到了這個題目,自己順手做做,居然仍然沒有太多的進步,最佳答案的思路在腦海裡面已經不...
演算法 檢測是否鍊錶存在環
這兒例子使用快慢指標的辦法實現。h lengthx e m e m lengthy m e lengthz length of circle lengthy lengthz 假定1.開始點是h,環的進入點是e,快指標和慢指標首次相遇的點是m.2.慢指標和快指標首次相遇在m點的時候,是慢指標首次到達m...