劍指offer 面試題23 鍊錶中環的入口結點

2021-10-02 22:35:03 字數 2767 閱讀 6979

開始行動,你已經成功一半了,獻給正在奮鬥的我們

乙個鍊錶中包含環,如何找出環的入口結點?如圖一,環的入口節點是3

(圖一)

這道題,首選用我們程式設計師的思維抽象一下,其實就是在遍歷鍊錶的時候找到第乙個重複節點,這個節點就是入環點,如果遍歷的過程中,寫乙個節點是空的話,就說明這個鍊錶不成環;

如果上面說的,你也想到了的話,那麼你一定會先想到使用雜湊表(hashmap),我們把每次遍歷的節點都判斷雜湊表中有沒有,沒有的話放到雜湊表中,有的話,這個節點就是入環點;這樣做,我們只需要遍歷一遍鍊錶,並且因為雜湊表的查詢時間複雜度可以看做o(1),所以我們最終的時間複雜度只需要o(n),也就是遍歷鍊錶所需要的時間複雜度,這樣看下來,這應該是最優解法,但是,這種解法卻也用了o(n)的空間複雜度,因為原則上,每乙個元素我們都要放到雜湊表中一次;

所以我們可問下面試官,這個對空間複雜度有沒有什麼要求,如果要求空間複雜度是常數階的話,那麼你就需要考慮更深層次的演算法了;

相信大家在學生時代應該都跑過步,操場一般都是圓的,那麼,乙個跑的快的同學,和乙個跑的慢的同學一直在上面跑,快的一定會扣慢的圈,對麼?

這就引申出來第乙個問題,我們怎麼判斷這個鍊錶有沒有環;

首先我們可以定義乙個快節點的引用fast,和乙個慢節點的引用slow(兩個同學,乙個跑的快的,乙個跑的慢的),兩個節點同時指向鍊錶的頭節點,然後等待開始,槍響之後,兩個節點同時向前移動,快的一次移動兩個節點,慢的移動乙個節點。基於上面的道理,如果鍊錶有環,快的就一定會在圓環上追上慢的,實則就是扣圈了。在程式上表現來說就是,fast == slow,這時兩個引用指向同乙個節點;如果鍊錶沒有環,快的在移動的過程中就一定會遇到前方沒有路的情況,也就是下一節點為空(但記住,快節點fast一次動兩個節點,所以要判斷下一節點和下下一節點是否為空);

如果題目是判斷鍊錶是否有環,上面的就是最優的答案;然而問題是入環的節點,如果快節點正好在入環處追上慢節點,那麼這就是正確答案;然而,大多數時候二者是在環內相遇;

到這,我們需要再明確一件事情,為什麼快節點一次要移動兩個節點,為什麼不是三個、四個,這樣不是更快到終點麼?如果這樣的話,你想過沒有,萬一慢節點正好被快節點跨過去了呢?拿圖一舉例,假設某一時間快節點處在節點3的位置,慢節點在節點4,那麼下一次移動快的到了6慢的到了5,沒有遇到,尷尬不?所以我們要明確,每一次移動,快節點都離慢節點近了乙個節點;

我們在來分析一下快慢節點算出的相遇點在什麼位置,假設,頭節點到入環點的距離是n(以圖一來說1到3的距離就為n),環的長度為k,那麼當慢節點走到入環點,快節點一定在慢節點前方n節點處。從這一刻開始,我們看做快的在追慢的話,那麼快節點還要追的距離就為k - n;也就是說,快節點會在距離入環點k - n的距離追上慢節點。這時,快慢節點距離入環點的距離均為n,那麼這時把快的放到鍊錶的頭節點,也是節點1處,並讓他們都按速度1來走,移動n次之後,就一定會在入環點相遇(切記讓快的放慢速度);但是如果k - n等於0(也是就開始節點即入環點,跑了一圈才發現開始的地方才是目的地),在這麼做就不對了,所以要判斷一下這是鍊錶是不是一整個環,就是在第一次相遇的時候看看相遇的節點是不是頭節點即可。

ps:這裡筆者使用的jdk為1.8版本

上面的**是用了乙個迴圈搞定的,所以在迴圈裡面要判斷快慢節點第一次相遇(就是剛起跑)的情況,不能算在內,第二次相遇如果是圓環的話,就是答案,如果不是的話,就要第三次相遇才是入環點;如果讀者理解起來有問題的話,可以先找到第乙個相遇點,判斷不是圓環之後再找第二個就是答案;我把這種寫法的**放到下面,大家可以任意選擇;

劍指offer(面試題23) 鍊錶中環的入口結點

題目 如果乙個單向鍊錶包含環,如何找出環的入口結點。include using namespace std struct listnode 檢查是否存在環 listnode checkcicle listnode phead else return null listnode findcirclee...

劍指Offer面試題23 鍊錶中環的入口節點

給乙個鍊錶,若其中包含環,請找出該鍊錶的環的入口結點,否則,輸出null。解題思路 解決這個問題可以分三步。1 第一步是確定乙個鍊錶中是否包含環。我們可以用兩個指標來解決這個問題。定義兩個指標,同時從鍊錶的頭結點出發,乙個指標一次走一步,另乙個指標一次走兩步。如果走得快的指標追上了走得慢的指標,那麼...

劍指offer 面試題 23 鍊錶中環的入口結點

給定乙個鍊錶,若其中包含環,則輸出環的入口節點。若其中不包含環,則輸出null。給定如上所示的鍊錶 1,2,3,4,5,6 2注意,這裡的2表示編號是2的節點,節點編號從0開始。所以編號是2的節點就是val等於3的節點。則輸出環的入口節點3.definition for singly linked ...