Floyd判圈算法
leetcode習題287 Find the Duplicate Number 在答案中看到了floyd’s tortoise and hare 算法,知道了如果有限狀態機、迭代函數或者鏈表存在環,那么是需要算法檢測環是否存在。檢測算法有三種:Floyd龜兔算法、Brent算法、Gosper算法。
Floyd龜兔算法
算法描述
Floyd龜兔算法是一種指針算法。該算法僅使用移動速度不同的兩個指針就能檢測出是否有環。Floyd龜兔算法解決以下問題:1檢測是否有環。2環的起點節點。3環的長度。
1 檢測是否有環。
想象在一個環形跑道上跑步,兩個人同時出發,出發以后速度快的人終究會在某一點和速度慢的人相遇。一般這個時候相遇,速度快的人比速度慢的人至少多跑一圈。
我們假設列表的開始節點是S,環上的起始節點是P,第一次相遇的節點是M。S和P的距離是p,從P和M的距離是m,從M到p的距離是n。指針t和h初始狀態下都指向S。接著t每次只有1步,h每次走2步。只要二者沒有相遇,就一直按著這個速度走下去。當h無法前進(到達隊列末尾)的時候,可以判斷沒有環。如果t和h在某點再次相遇,則確定有環。
舉一個迭代函數的例子。有函數f定義域和值域都是 S = {0,1,2,3,4,5,6,7,8},從x0=2x_0=2x0?=2開始,不斷重復調用f,能夠產生一個序列:2,0,6,3,1,6,3,1,6,3,1…產生了一個環:6,3,1。
定義:S是一個有限集合,f是一個函數,從S到S的一個映射,x0x_0x0?可以是S中的任意一個元素。對于任意的i>0i>0i>0,xi=f(xi?1)x_i=f(x_{i-1})xi?=f(xi?1?)。μ\muμ是換上的起點節點的最小下標,λ\lambdaλ是環的長度。一定有xμ=xλ+μx_\mu=x_{\lambda+\mu}xμ?=xλ+μ?
證明:如果有環存在,則對于任意的整數i>=μi>=\mui>=μ并且k>0k>0k>0,都有xi=xi+kλx_i=x_{i+k\lambda}xi?=xi+kλ?。對于特定的k來講,一定存在使得i=kλi=k\lambdai=kλ,那這時候xi=x2ix_i=x_{2i}xi?=x2i?。至此,說明了速度不同的兩個指針可以在某點相遇。
2 計算環長度
當t和h相遇在M點。因為相遇的點一定在環上。這時候保存h不動,t按之前的速度繼續前進,直到和h再次相遇,這個過程中移動的步數就是環的長度。
3 環的起始節點確定
在確定是否有環的過程中,h走的距離是t走的距離的2倍。c為環長。t走的距離是 s1=p+m+a?cs1=p+m+a*cs1=p+m+a?c,h走的距離是2?s1=p+m+b?c2*s1=p+m+b*c2?s1=p+m+b?c,兩式子相減得到:s1=(b?a)?c=p+m+a?cs1=(b-a)*c=p+m+a*cs1=(b?a)?c=p+m+a?c,得到p+m=環的整數倍。
為了找到環的起點,t回到起點,h在當前位置。同時向前,他們再次相遇一定在P點。為什么呢?因為從S到P的距離是p,從P到M的距離是m,因為m+p是環長的整數倍,所以當h走過距離p的時候也一定達到了P點。
算法時間復雜度:令S到P的距離為m,環的長度為n,時間復雜度O(m+n)O(m+n)O(m+n)。
空間復雜度:O(1)。
參考
網頁1
網頁2
網頁3
總結
- 上一篇: Web前端:7大Web开发趋势和技术
- 下一篇: Android中弹出对话框,AlertD