[數據結構] 如何判斷一個鏈表是否有環? 環的入口? 環的長度?


練習算法的時候, 遇到這個問題, 感覺挺有意思的, 所以記錄下來.

在網上參考了這個答案:
https://blog.csdn.net/thefutureisour/article/details/8174313

但是后來又自己想了一下, 用自己的思維思考了一遍, 感覺更加清晰明了.

問題是:

  1. 如何判斷一個鏈表是否有環?
  2. 環的長度如何計算?
  3. 如何找到環的入口?

我們先看圖說話:

假設鏈表長度為7, 我們用 L 表示, 設有兩個指針, P1和P2, 速度分別為1, 2, (P1 一次走1個結點, P1 一次走2個結點), 同時從 Node1出發.
那么請問: 何時P2再次趕上P1呢? 這是一個很有意思的問題. 就像以前的運動會長跑跑圈一樣, 快的總會追上慢的.

我們要明白一個道理:
無論 P1 轉了幾圈, P2 第一次追上 P1 的時候, P2 一定比 P1 多走一圈而已!!

我們設 時間為 X 時, P2追上P1, 有表達式:
P1走的距離 + 一圈的長度 = P2走的距離
即為:
X * 1 + L = X * 2
化簡為:
X = L
L = 7, 所以, P1和P2從 Node1出發后又一次且是第一次在 Node1相遇, 因為剛好走了一圈, 一圈長度為7.

我們再來看一個復雜的情況:
假設鏈表不是整個環, 而是從中間某一點開始有環的. 那么好像一下復雜了不少, 一下子有點繞不過彎了呢! 我是這樣子的, 所以我想了好一會.
我們先來看圖.

但是道理還是一樣的.
無論環的入口在哪里,
無論 P1 和P2 在環里轉了幾圈, P2 第一次追上 P1 的時候, P2 一定比 P1 多走一圈環的長度而已!!

我們設 時間為 X 時, P2追上P1, 有表達式:
P1走的距離 + 此時環一圈的長度(記為C) = P2走的距離
即為:
X * 1 + C = X * 2
化簡為:
X = C

在這張圖中, 我們知道 C=5, P1和P2在 Node6處相遇, 因為是從 Node1出發的, P1走了5個時間單位, 速度為1.

更加一般的情況是, C = (V2-V1)* X, V2代表P2的速度, V1代表P1的速度, 我們為了方便表示, 簡單令其為2 和 1 罷了.
既然我們知道了C的長度, 那么如何求 環的入口呢?

有兩種辦法:

  1. 用鏈表的長度 L 減去C, 即可得到從出發點走幾步,就到了 環的入口. 比如這里, 7-5=2, 走兩步, 環的入口是Node3.
  2. 如果我們沒有求出C的長度怎么玩呢?
    我們知道, 環的入口, 其實也是鏈表的尾結點, 和Node1的距離, 是L-C, 因為環的長度為C, 鏈表總長度為L, 而這段不在環內.

同時, 我們記相遇點為 NodeX, NodeX到 環的入口, 也就是尾結點的距離, 為 L-C. ? 如何理解, 下面是證明步驟:

因為P1從Node1出發走了X個時間長度單位到NodeX, 而剩下的長度為L-X, 而C=X.
所以, 所以NodeX到環的入口的距離為 L-C,
如果此時 再讓 另一個指針P3 以和P1相同的速度出發往前走, 那么, P1和P3必然在環的入口相遇.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM