參考:
上面分析了 根據這張圖
推倒出 數學公式。 剛接觸 不能一下弄明白。下面結合上面文章的分析。仔細推倒一下 ,
一般設定 快指標 速度是 慢指標的2倍。及 快指標每次遍歷兩個指標, 慢指標每次遍歷1個指標。
假設上圖 快慢指標 在e點相遇,那 相遇點離迴圈節點d 之間距離是x. 頭結點a 離迴圈節點d 距離為k.
那麼在兩指標相遇時,各自走過得距離(這裡可以吧上圖想成是 乙個操場,起點不在操場內):
慢指標:
k + x + n*(x+y) = m;//x+y 繞環一圈的距離;n 慢指標 總共繞了幾圈在環內.
快指標:
試想下 快指標是慢指標 速度的2倍,當它們相遇時 所用的時間是一樣的。那麼快指標 走過得距離是
2*m;
也等於k+x +n*(x+y) = 2*m;//n為快指標繞過得圈數
聯立做差上面兩公式。
(n-n)*(x+y) = m; 及
(n-n)*(x+y) = k+x+n*(x+y);//這裡x+y 環長是個定值。 假設環長為m
有:(n-n)*m = k+x+n*m;
有:k+x = (n-2*n)*m ;
最終的推倒公式 出來啦。及頭節點a 到 迴圈節點d 的距離 加上 相遇點e離迴圈節點d 是 環長的整數倍。
這個公式試用於 0 型迴圈鍊錶 和 6型迴圈鍊錶。
對於前者 起k 和 x 都為0;快慢指標起點都是迴圈節點(0型 任意一點都是迴圈節點)
那麼有 (n-2*n)*m = 0;
及 n = 2*n; 相遇時 快慢指標所繞 環的圈數 前者是後者的2倍。 可以想象速度是2唄,所用時間相同。
這裡跟環有多少節點沒有關係。
上面只是找到了相遇節點。如何找到迴圈節點。對於6型迴圈鍊錶。
還是上面推倒公式:
k+x = (n-2*n)*m;//假設n-2*n = q; 單位為圈數。
有k+x=q*m; //再假設快慢指標能再迴圈節點相遇,那麼x = 0;
k = q*m; //q 的值和k 成正比,這個公式成立條件是 快慢指標相遇 在環上的任意乙個點,
假如是e點,結合公式 從e點轉q*m個節點 正好= k 。k的終點正好是迴圈節點d,及 如果快指標從起點a 走過k 和 慢節點 從e 走過m*q 相遇節點正好是d迴圈節點,前提是快慢指標速度相同。
假設將快指標 從頭節點開始。慢指標從上次快慢指標相遇點 開始。 兩者已相同速度移動。
當快指標走的d 迴圈節點走過距離為k,慢指標 走到d 迴圈節點走過的距離為q*m;
此時 二者相遇 節點就是迴圈節點。
分析下**:
node* findbeginning(node *phead)關於快慢指標演算法:if (null == fast->pnext) //
判斷是哪種情況導致跳出迴圈
return
null;
/*查詢環起點
*/fast =phead;
while (fast !=slow)
return
fast;
}
不僅限於 迴圈鍊錶問題。
比如查詢乙個 未知長度鍊錶中中心節點
可以先遍歷長度,在遍歷到長度/2處返回節點。顯然這樣 演算法不夠優化,
使用快慢指標 遍歷。快指標速度為 慢得 2倍。
快指標遍歷完,返回的慢指標 正好是 長度/2 的節點。
鍊錶迴圈節點問題
題目描述 給定乙個鍊錶,返回迴圈開始的節點。如果沒有迴圈節點,return null,並且要求在不占用額外空間的情況下解決 解題思路 1 快慢節點確定是否會相交,若迴圈,則快慢指標會相交,若不迴圈,則快指標會指向空 2 若相交,記錄慢指標位置,並讓快指標回到頭結點,兩指標再一起走,第乙個相交點,為迴...
利用快慢指標尋找鍊錶中間節點
876.鍊錶的中間結點 這道題要求我們找到鍊錶中的中間位置,首先想到第一種方法,使用兩個指標,乙個從頭遍歷到尾部確定長度,乙個從頭遍歷到相應位置。那麼有沒有一遍遍歷就能解決的?那麼我們想到快慢指標,因為快慢指標往往可以做到一遍遍歷,在慢指標處找到答案 做法 慢指標走一步,快指標走兩步。這樣快指標到末...
鍊錶的快慢指標 查詢中點
一直做題都是陣列中點,直接算n 2,但是鍊錶的中點怎麼求出來,我還真沒見過,只能說自己做題太少了。今天做leetcode上的題就遇到了,雖然說簡單,但對我來說這是個新的知識點,我得記錄一下,如下 cpp view plain copy listnode findmidnode listnode he...