斐波那契數列數列的三種時間複雜度的實現方法

  給定整數N,返回斐波那契數列的第N項

斐波那契數列爲1,1,2,3,5,8,......也就是除第1項和第2項爲1以外,對於第N項,有F(N)=F(N-1)+F(N-2),於是能夠很輕鬆的寫出暴力遞歸的代碼。其時間複雜度爲O(2^N).

int Fibonacci1(int n)
{
   if(n<1)return 0;
   if(n==1 || n==2) return 1;
   return Fibonacci1(n-1)+Fibonacci1(n-2);
}
int main()
{
    int result = Fibonacci1(30);
    cout<<result<<endl;
    return 0;
}

斐波那契數列也可以從左到右依次求出每一項的值,那麼通過順序計算求得第N項即可。其時間複雜度爲O(N)。

int Fibonacci2(int n)
{
   int tmp=0;
   int res=1;
   int pre=1;
   if(n<1)return 0;
   if(n==1 || n==2) return 1;
   for(int i=3;i<=n;i++)
   {
       tmp=res;
       res=res+pre;
       pre=tmp;
   }
   return res;
}
int main()
{
    int result = Fibonacci2(30);
    cout<<result<<endl;
    return 0;
}

如果遞歸式嚴格遵循F(N)=F(N-1)+F(N-2),對於求第N項的值,有矩陣乘法的方式可以將時間複雜度降至O(logN)。F(N)=F(N-1)+F(N-2),是一個二階遞推數列,一定可以用矩陣乘法的形式表示,切狀態矩陣爲2*2的矩陣:

(F(N),F(N-1))=(F(N-1),F(N-2))*| {a,b},{c,d}|

把斐波那契數列的前4項帶入可得:a=b=c=1;d=0

原公式可簡化爲:

(F(N),F(N-1))=(F(N-1),F(N-2))*| {1,1},{1,0}| = (1,1)*| {1,1},{1,0}|^(n-2)

求斐波那契數列第N項的問題就變成了如何用最快的方法求一個矩陣N次方的問題,而求矩陣N次方的問題明顯是一個能夠在O(logN)時間內解決的問題。爲了表示方便,用求一個整數N次方的例子來說明,因爲只要理解了如何在O(logN)的時間複雜度內求整數N次方的問題,對於求矩陣N次方的問題是同理的,區別是矩陣乘法和整數乘法在細節上有些不一樣,但兩者道理相同。

將設一個整數10,如何最快的求10的11次方

1. 11的二進制形式爲1011.

2. 10的11次方=10^8 * 10^2 * 10^1。

在這個過程中,我們先求出10^1,然後根據10^1求出10^2,再根據10^2求出10^4,......,最後求出10^8,即11的二進制數形式總共多少位,就使用了幾次乘法。

3. 在步驟2進行的過程中,把應該累乘的值相乘即可,比如10^8、10^2、10^1應該累乘,因爲8,2,1對應到11的二進制數中,相應位上是1;而10^4不應該累乘,因爲4對應到11的二進制數中,相應位上是0。

#include <iostream>
#include<stdlib.h>

using namespace std;

 struct matrix{
        int m[2][2];
    }ans;

    matrix mulimatrix(matrix &m1, matrix &m2){
        matrix res0;
        for(int i=0; i<2; i++){
            for(int j=0; j<2; j++){
                res0.m[i][j]=0;
                for(int k=0; k<2; k++){
                    res0.m[i][j] += m1.m[i][k]*m2.m[k][j];
                }
            }
        }
        return res0;
    }

    matrix matrixpower(matrix &mat, int p){
        matrix tmp=mat;
        matrix res1;
        for(int i=0; i<2; i++){
            res1.m[i][i]=1;
        }
        res1.m[0][1]=0;
        res1.m[1][0]=0;
        for( ; p != 0; p >>= 1){
            if((p&1)!=0){
                res1 = mulimatrix(res1,tmp);
            }
            tmp = mulimatrix(tmp,tmp);
        }
        return res1;
    }

    int Fibonacci(int n) {
        if(n<1)return 0;
        if(n==1 || n==2) return 1;
        matrix base = {1,1,1,0};

        matrix res= matrixpower(base, n-2);


        int result= res.m[0][0] + res.m[1][0];

        return result;
    }

int main()
{
    int result = Fibonacci(30);
    cout<<result<<endl;
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章