1. 程式人生 > >Floyd判圈算法(判斷鏈表是否含環)

Floyd判圈算法(判斷鏈表是否含環)

鏈表是否有環 als 龜兔賽跑算法 code 狀態 如果 inline span -s

Floyd判圈算法

簡介

Floyd判圈算法,也稱龜兔賽跑算法,可用於判斷鏈表、叠代函數、有限狀態機是否有環。如果有,找出環的起點和大小。時間復雜度O(n),空間復雜度O(1)。

可以先思考一下,假設有一個圓形的跑道周長為\(C\),A和B從同一個起點,分別以\(v\)\(2v\)的速度同向出發,可以知道,因為B比A跑得快而且跑道是環形的,所以接下來一定存在某一時刻,B和A相遇,這時候,B跑過的總距離\(S_B\)減去A跑的總距離\(S_A\)一定是\(C\)的整數倍。即: \(S_B-S_A = k*C, k=1,2,...\)

算法思路

在判斷鏈表是否有環的問題中,可以使用Floyd算法來判斷。

使用2個指針,一個快(fast)一個慢(slow),初始化兩個指針在起始位置。每次fast向前走兩步,slow向前走一步。若fast到達了終點,則證明鏈表中有環。若fast和slow再次相遇,則說明鏈表中含環。

例題

leetcode202. Happy Number

題意:
判斷某個數字是不是happy number.
happy number滿足一下幾點:
以任意正整數開頭,用它各個位置上數字的平方和生成一個新的數字。
對於該新的數字,重復上述步驟,如果最後生成的數字是1。則原始數字是happy number。
解法一:
借助set容器,每次生成的數字放入set中,如果出現了重復,即說明出現了循環,則該數字不是happy number.
解法二:


等價於判斷是否有環。用Floyd算法判斷是否有環。

解法二代碼:

class Solution{
public:
    int cal(int n){
        string s=to_string(n);
        int sum=0;
        for(char num:s){
            sum += (num-‘0‘)*(num-‘0‘);
        }
       // cout<<"sum: "<<sum<<endl;
        return sum;
    }
    bool isHappy(int n){
        int slow=n, fast=n;// 初始化
        while(slow!=1 && fast!=1){
            slow = cal(slow);// 走一步
            if(slow==1) return true;
            fast = cal(cal(fast));//走兩步
            if(slow==fast) return false;
        };
        return true;
    }
};

Floyd判圈算法(判斷鏈表是否含環)