【外企面試】求一個鏈表中環的入口【強勢證實】

此題沒有代碼,是一道面試題。題目很好理解,有個鏈表,先判斷是否有環,若是有環則求出環的入口。面試

這道題跟好幾位offer收割機討論過,基本都是已知leetcode或哪裏的方法,證實該方法的正確性。指針

我和我家陽哥,試圖證實,策略是能夠推導出來的。證實以下:code

首先,要判斷一個鏈表是否有環,機智的作法是快慢指針,令快指針fast每次走兩步,慢指針slow每次走一步,那麼fast若是能和slow相遇,就證實,鏈表中有環。leetcode

那麼有環以後,如何尋找環的入口呢?ast

(1)首先,咱們定義幾個變量:變量

  • ListHead表示鏈表頭
  • RingEntry表示環入口指針
  • x表示ListHead與RingEntry之間的距離(兩個相鄰節點間的距離爲1)
  • pos表示slow第一次走到RingEntry時,fast所在位置與RingEntry之間的距離,假設入環後順時針走
  • y表示slow與fast的相遇點與RingEntry之間的距離
  • r表示環的長度(環中節點個數-1)

(2)其次,咱們須要證實一個結論---slow入環後,一圈以內一定與fast相遇List

         這個結論其實很好證實,咱們用反證法。假設slow走了一圈又回到了RingEntry,這一過程當中,都沒與fast相遇。當slow回到RingEntry時,fast一定在距RingEntry爲pos的位置。這一狀態與slow剛入環時的狀態同樣,在這一圈中slow與fast都沒有相遇,那麼以後只會不斷重複以前的路徑,永不會相遇。方法

        由於咱們堅信 有環的話,slow和fast必相遇的,於是上述假設不成立,slow入環後,一圈以內一定與fast相遇。鏈表

(3)有了(2)的結論,就能夠得出下列等式:co

  • slow首次到達RingEntry時,走了x步,此時fast應該走了2x的距離。又fast位於距離RingEntry爲pos,那麼:

   2x = x + k * r + pos(k表示fast在環中已經繞的圈數) ------>    pos = x - k * r

  • slow能夠看作是比fast快了 r - pos步,又slow與fast相遇時,slow走了y步,於是有:

   2y - y = r - pos ------> y = r - pos

  • 從相遇點開始,slow至少再向前 r - y 步就能夠到達環入口了,那麼

     r - y = r - r + pos = pos = x - k * r ------> r - y + k * r = x

         之因此要把k * r移到 等號 的左邊,是由於 k * r 表明着繞着環 k 圈,到達的位置仍是 r - y步後到達的位置。

根據最後一個等式,咱們就能夠看出,slow再向前走 x 步 必定會到RingEntry。

因此尋找環入口的方式爲:相遇點後,slow 從相遇點開始,tmp從 ListHead 開始,同時每次走一步,兩個相遇點就是RingEntry!

相關文章
相關標籤/搜索