聊天時聽到的這個問題,即有乙個單鏈表,可能有環(見圖),請判斷出是否存在這個環?既然有個環,那就直接遍歷一遍環唄,用個陣列標記一下。時間複雜度和空間複雜度都是o(n)。貌似這是很常見的面試題(我居然沒印象)。
這個思路的問題就是在於空間複雜度是o(n),所以面試中,面試官總會再問,有沒有更好的解決方法。然後我表示我只能想到這個。。。然後果斷就悲劇了。
然後我就查到這個快慢指標法了。。。(看來看點面試題還是有必要的)
說實話,這個方法以前見到過,但是還真沒記住。看到這個問題時完全沒印象,直到說乙個走一步乙個走兩步時才隱約想起。(這果斷就是被刷的節奏)
快慢指標法就是用兩個指標(好心的面試官還是會提醒一下的),指標a一次走一步,指標b一次走兩步。如果有環,必然會在某個時間走到同乙個點上,否則,b指標會先過末尾(可能長度為奇數)。
其實,乙個走一步,乙個走兩步,很容易讓人想起追及問題,當然不完全等同,追上和同時走到乙個點不是同乙個概念,後者是離散的。
但是當二者的步數差為1的時候,奇蹟就發生了。如果鍊錶有環,那麼兩個指標必然最後都會到環裡。我們可以認為a始終在b的前面,同一方向嘛。b每次跳躍都會離a近一步,環又可以認為是無限遠的,所以總會追到,在某個時刻兩個指標位於同個節點。
上面證明了如果有環它們必然會相遇,但是會在**相遇呢,如何找到那個入口點呢(面試官果斷會這麼問)。
設起點到入口(類似上圖a->d)距離為x(步)。那個環的長度(類似上圖d->j->d)為y(步)。a指標速度為1,b指標速度為2,時間設為t。
那麼,如果兩個指標走到同乙個節點,就會有這麼乙個等式:(1*t-x)%y=(2*t-x)%y這個應該很容易看懂,a指標和b指標走過的路程減去環外的那段,對環的長度取摸必然是相等的。
簡化一下那個等式,我們就會發現t%y=0;於是就得到乙個結論,只要時間t是環長度y的倍數,則兩個指標走到同個節點。這時我們可以假設t=b*y,乙個y的倍數。那麼在環內的位置就是(2*b*y-x)%y 。環的入口應該就是當(v*t-x)%y=0的時候,v是速度(步伐數)。對比一下就能發現,只要從兩個指標的相遇點再前進x步就能到達環入口。
至此,問題已經解決,至於實現方面,x步可以存個變數,如果要求只能用兩個指標,那就用其中乙個指標從起點往入口點走,另乙個指標從相遇點往前走,相遇之時就是到入口點之時。
說實話,如果沒聽說過快慢指標這個演算法,還真想不到。這個演算法也有稱為奇偶指標的,因為乙個一步,乙個兩步。我覺得真正關鍵的點是在於兩個指標的步伐差1。
最後的用兩個指標找入口點的走法,是把長度轉換為了時間,度量除了x的長度。比較巧妙。
如果我乙個走3步,乙個走4步呢?還是能得出答案。關鍵點在於步伐差一。至於這樣是不是更快呢?恐怕實際情況並不是二者步伐越長越好,因為雖說步伐數大了,進入環快了,但是在環中繞的圈數可能反而增加。所以沒有必要加大步伐數。
C 單鏈表 判環
題源 牛客網 直通bat面試演算法精講課 題目 給定乙個單鏈表的頭結點head,判斷其是否有環,無環返回 1 有環返回 入環 的 第乙個 結點的 數值。要求 如果鍊錶長度是n個節點,請做到 時間複雜度為o n 額外空間複雜度為o 1 演算法思想的說明 1.單鏈表 每個結點只有 乙個next域 或者稱...
單鏈表判環判交問題
摘要 有乙個單鏈表,其中可能有乙個環,也就是某個節點的next指向的是鍊錶中在它之前的節點,這樣在鍊錶的尾部形成一環。1 如何判斷乙個鍊錶是不是這類鍊錶?2 如果鍊錶為存在環,如果找到環的入口點?擴充套件 判斷兩個單鏈表是否相交,如果相交,給出相交的第乙個點。有乙個單鏈表,其中可能有乙個環,也就是某...
單鏈表判環判相交綜合題
給定兩個單鏈表的頭節點head1和head2,單鏈表可能有環,也可能無環。如何判斷兩個鍊錶是否相交?相交的話返回相交的第乙個節點,不想交的話返回null。要求 如果鍊錶1的長度為n,鍊錶2的長度為m,時間複雜度o n m 額外空間複雜度o 1 首先我們先判定兩個鍊錶是否有環,如果只有其中乙個鍊錶有環...