Floyd判圈算法(Floyd's cycle detection
Floyd判圈算法(Floyd Cycle Detection Algorithm),又稱龜兔賽跑算法(Tortoise and Hare Algorithm)。該算法由美國科學家羅伯特·弗洛伊德發明,是一個可以在有限狀態機、迭代函數或者鏈表上判斷是否存在環,求出該環的起點與長度的算法。
?? ? ??如果有限狀態機、迭代函數或者鏈表上存在環,那么在某個環上以不同速度前進的2個指針必定會在某個時刻相遇。同時顯然地,如果從同一個起點(即使這個起點不在某個環上)同時開始以不同速度前進的2個指針最終相遇,那么可以判定存在一個環,且可以求出2者相遇處所在的環的起點與長度。
算法描述
如果有限狀態機、迭代函數或者鏈表存在環,那么一定存在一個起點可以到達某個環的某處(這個起點也可以在某個環上)。
初始狀態下,假設已知某個起點節點為節點S。現設兩個指針t和h,將它們均指向S。
接著,同時讓t和h往前推進,但是二者的速度不同:t每前進1步,h前進2步。只要二者都可以前進而且沒有相遇,就如此保持二者的推進。當h無法前進(或者是t,有一個就可以),即到達某個沒有后繼的節點時,就可以確定從S出發不會遇到環。反之當t與h再次相遇時,就可以確定從S出發一定會進入某個環,設其為環C。
如果確定了存在某個環,就可以求此環的起點與長度。
計算環長度
上述算法剛判斷出存在環C時,顯然t和h位于同一節點,設其為節點M。顯然,僅需令h不動,而t不斷推進,最終又會返回節點M,統計這一次t推進的步數,顯然這就是環C的長度。
計算環起點
?
為了求出環C的起點,只要令h仍位于節點M,而令t返回起點節點S。隨后,同時讓t和h往前推進,且保持二者的速度相同:t每前進1步,h前進1步。持續該過程直至t與h再一次相遇,設此次相遇時位于同一節點P,則節點P即為從節點S出發所到達的環C的第一個節點,即環C的一個起點。
鏈表起點為節點S,環起點為節點P,t和h相遇時位于同一節點M,S和P之間的距離為p,P和M之間的距離為m,環長為C,這里兩點之間的距離是指從一點走多少步可以到點另外一點。
當t和h相遇時,
t走的步數,step = p + m + a * C,a表示相遇時t走的圈數?
h走的步數,2 * step = p + m + b * C,b表示相遇時h走的圈數
兩者相減:step = (b - a) * C = p + m + a * C,由此可知t走的步數是環C的倍數,即 p + m 剛好是環長度C的倍數。
t和h在M處相遇,為了計算環C的起點,令h仍位于節點M,而令t返回起點S,隨后,同時讓t和h往前推進,且保持兩者的速度相同:t每前進1步,h前進1步。持續該過程直至t與h再一次相遇,則它們此次相遇時一定位于環的起始節點P。為什么它們此次相遇時一定在環起始節點呢?
t走了p步到達P,h在環C上p步在哪呢?h從M處出發走了p步,相對于環起始位置,h走過的距離是 m + p,而m + p剛好是環長度C的倍數,即h此時也位于環起始節點處,即t和h在P處相遇。據此就可以計算出環起始節點的位置。
算法復雜度
時間復雜度
注意到當指針t到達環C的一個起點節點P時(此時指針h顯然在環C上),之后指針t最多僅可能走1圈。若設節點S到P距離為,環C的長度為,則時間復雜度為,是線性時間的算法。
空間復雜度
僅需要創立指針t、指針h,保存環長n、環的一個起點P。空間復雜度為,是常數空間的算法。
應用
對于有限狀態機與鏈表,可以判斷從某個起點開始是否會返回到訪問過運行過程中的某個狀態和節點。
對于迭代函數,可以判斷其是否存在周期,以及求出其最小正周期。
https://blog.csdn.net/javasus/article/details/50015687
leetcode 202 快樂數
最終迭代下去,得到的和不管是不是1都是小于10的
https://leetcode-cn.com/problems/happy-number/
leetcode ?141. Linked List Cycle
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/ class Solution { public:bool hasCycle(ListNode *head) {if(head==NULL)return false;ListNode *slow;ListNode *fast;slow = fast = head;do{slow = slow->next;fast = fast->next;if(fast!=NULL) fast = fast->next;}while( fast != NULL &&slow != NULL &&slow->val!=fast->val);if(fast==NULL || slow==NULL) return false;else return true;} };leetcode?142. Linked List Cycle II
測試數據
很能說明走到的相遇的位置和相遇的一道題
?
總結
以上是生活随笔為你收集整理的Floyd判圈算法(Floyd's cycle detection的全部內容,希望文章能夠幫你解決所遇到的問題。