Floyd判圈演算法

2022-09-18 13:21:11 字數 1329 閱讀 1536

**自

問題:如何檢測乙個鍊錶是否有環,如果有,那麼如何確定環的起點.

龜兔解法的基本思想可以用我們跑步的例子來解釋,如果兩個人同時出發,如果賽道有環,那麼快的一方總能追上慢的一方。進一步想,追上時快的一方肯定比慢的一方多跑了幾圈,即多跑的路的長度是圈的長度的倍數。

基於上面的想法,floyd用兩個指標,乙個慢指標(龜)每次前進一步,快指標(兔)指標每次前進兩步(兩步或多步效果是等價的,只要乙個比另乙個快就行,從後面的討論我們可以看出這一點)。如果兩者在煉表頭以外的某一點相遇(即相等)了,那麼說明鍊錶有環,否則,如果(快指標)到達了鍊錶的結尾,那麼說明沒環。

環的檢測從上面的解釋理解起來應該沒有問題。接下來我們來看一下如何確定環的起點,這也是floyd解法的第二部分。方法是將慢指標(或快指標)移到鍊錶起點,兩者同時移動,每次移動一步,那麼兩者相遇的地方就是環的起點。

假設起點到環的起點距離為m,已經確定有環,環的周長為n,(第一次)相遇點距離環的起點的距離是k。那麼當兩者相遇時,慢指標移動的總距離為i,i = m + a * n + k,因為快指標移動速度為慢指標的兩倍,那麼快指標的移動距離為2i,2i = m + b * n + k。其中,a和b分別為慢指標和快指標在第一次相遇時轉過的圈數。我們讓兩者相減(快減慢),那麼有i = (b - a) * n。即i是圈長度的倍數。利用這個結論我們就可以理解floyd解法為什麼能確定環的起點。將乙個指標移到鍊錶起點,另乙個指標不變,即距離鍊錶起點為i處,兩者同時移動,每次移動一步。當第乙個指標前進了m,即到達環起點時,另乙個指標距離鍊錶起點為i + m。考慮到i為圈長度的倍數,可以理解為指標從鍊錶起點出發,走到環起點,然後繞環轉了幾圈,所以第二個指標也必然在環的起點。即兩者相遇點就是環的起點。 

例項程式如下:

1 int *head = list.gethead();

2 if (head != null)

15 16 fastptr = fastptr->next->next;

17 slowptr = slowptr->next;

18 } while (fastptr != slowptr);

19 //確定環的起點

20 slowptr = head;

21 while(slowptr != fastptr)

22

26 cout<<"the starting point of the cycle is "<27 }

之後的面試中問到如何確定環的長度。當然,如果在確定環的起點後再跑一圈就可以,但這樣就小題大作了。在確定有環後,再讓快的和慢的指標跑一圈,再次追上後,快的比慢的正好多跑一圈,這就求出了環的長度。

Floyd判圈演算法

參考 判斷鍊錶中是否有環 大概就是說兩個指標首先都指向鍊錶的首部,然後乙個每次走一步,乙個每次走兩步,如果有環,那麼慢的肯定能夠追上快的,否則快的就會先到達終點。求環的長度 兩個指標重合時,快的停止,慢的每次走一步,計算圈的長度。求環的起點 if head null slowptr slowptr ...

floyd判圈演算法

floyd判圈演算法又稱龜兔賽跑演算法 兩個指標 p1,p2 p1 每次向後跳一次 p2 每次向後跳兩次 顯然,如果 p1,p2 相遇才有環 現在我們想求環長和環的起點.設起點到環的距離為 len 環的起點離相遇點距離 rem 設兩個指標分別走了 p,q 步 那麼,p len rem a l,q l...

UVA 11549 floyd判圈演算法

題意 給乙個整數k,每次平方後只能顯示結果的前n位,問在這個過程中能得到的最大的數是多少 思路 floyd判圈演算法 它的正確性建立在這得到的這些數是有限的,所以一定是乙個迴圈,在這個迴圈的圈裡面,乙個快乙個慢,同時出發最後一定會再次相遇,此時結束 在這個過程中得到最大值 ac include in...