フィボナッチ数列を解き、時間の複雑さを計算する3つの方法

フィボナッチ数列についての簡単な紹介:

  ゴールデンセクションシーケンスとも呼ばれるフィボナッチ数列は、0、1、1、2、3、5、8、13、21、34などのシーケンスを指します。数学では、フィボナッチ数列これは次のように再帰的に定義されます:F(0)= 0、F(1)= 1、F(n)= F(n-1)+ F(n-2)(n≥2、n∈N* )現代の物理学、準結晶構造、化学などの分野では、フィボナッチ数列が直接応用されているため、アメリカ数学会は1963年から「フィボナッチ数列」というタイトルの数学を発表しています。この領域の研究結果を公開するために使用される雑誌。

特定のトピック:

フィボナッチ数列のF(n)を解くために一般的に使用される3つのアルゴリズムがあります。再帰アルゴリズムと非再帰アルゴリズム、および行列の高速パワーです。3つのアルゴリズムの時間の複雑さを分析してみてください。

1.再帰的アルゴリズム

Fib(5)の再帰呼び出しプロセス

#include<iostream>
using namespace std;

long Fibonacci(int n) {
    if (n == 0)
        return 0;
    else if (n == 1)
        return 1;
    else
        return Fibonacci(n - 1) + Fibonacci(n-2);
}

int main() {
    cout << "Enter an integer number:" << endl;
    int N;
    cin >> N;
    cout << Fibonacci(N) << endl;
    system("pause");
    return 0;
}

時間の複雑さの分析:

  F(n)を解くには、F(n-1)とF(n-2)を最初に計算し、F(n-1)とF(n-2)を計算し、F(n-3)とFを最初に計算する必要があります(n-4)。以下同様に、最初にF(1)とF(0)を計算し、次にF(n-1)とF(n-2)の結果を逆に取得して、F(n)を取得して多くの繰り返し値を計算する必要があるまで、時間の無駄をたくさん引き起こし、アルゴリズムの時間の複雑さはNの増加に伴って指数関数的に増加し、時間の複雑さはO(2 ^ n)、つまり2のn乗

2.非再帰アルゴリズム

#include<iostream>
using namespace std;

long Fibonacci(int n) {
    if (n <= 2)
        return 1;
    else {
        long num1 = 1;
        long num2 = 1;
        for (int i = 2;i < n - 1;i++) {
            num2 = num1 + num2;
            num1 = num2 - num1;
        }
        return num1 + num2;
    }
}

int main() {
    cout << "Enter an integer number:" << endl;
    int N;
    cin >> N;
    cout << Fibonacci(N) << endl;
    system("pause");
    return 0;
}

時間の複雑さの分析:

   n(> 2)から計算し、F(n-1)とF(n-2)の加算を使用して結果を検索します。これにより、多くの繰り返し計算が回避され、その効率は再帰アルゴリズムよりもはるかに高速です、アルゴリズムの時間複雑度はnに比例します。つまり、アルゴリズムの時間複雑度はO(n)です。

3.行列乗算+高速パワー

ここに画像の説明を書きます

したがって、f(n)の計算は、行列の(n-2)乗を計算するために簡略化され、行列の(n-2)乗を計算するために、分解できます。つまり、行列(n-2)/ 2乗を計算します。行列のべき乗を半分ずつ計算するため、段階的に2乗して分解し、時間の複雑さはO(log n)です。

#include <iostream>
using namespace std;

class Matrix
{
public:
    int n;
    int **m;
    Matrix(int num)
    {
        m=new int*[num];
        for (int i=0; i<num; i++) {
            m[i]=new int[num];
        }
        n=num;
        clear();
    }
    void clear()
    {
        for (int i=0; i<n; ++i) {
            for (int j=0; j<n; ++j) {
                m[i][j]=0;
            }
        }
    }
    void unit()
    {
        clear();
        for (int i=0; i<n; ++i) {
            m[i][i]=1;
        }
    }
    Matrix operator=(const Matrix mtx)
    {
        Matrix(mtx.n);
        for (int i=0; i<mtx.n; ++i) {
            for (int j=0; j<mtx.n; ++j) {
                m[i][j]=mtx.m[i][j];
            }
        }
        return *this;
    }
    Matrix operator*(const Matrix &mtx)
    {
        Matrix result(mtx.n);
        result.clear();
        for (int i=0; i<mtx.n; ++i) {
            for (int j=0; j<mtx.n; ++j) {
                for (int k=0; k<mtx.n; ++k) {
                    result.m[i][j]+=m[i][k]*mtx.m[k][j];
                }   
            }
        }
        return result;
    }
};
int main(int argc, const char * argv[]) {
    unsigned int num=2;
    Matrix first(num);
    first.m[0][0]=1;
    first.m[0][1]=1;
    first.m[1][0]=1;
    first.m[1][1]=0;
    int t;
    cin>>t;
    Matrix result(num);
    result.unit();
    int n=t-2;
    while (n) {
        if (n%2) {
            result=result*first;
            }
        first=first*first;
        n=n/2;
    }
    cout<<(result.m[0][0]+result.m[0][1])<<endl;
    return 0;
}

この記事はリソースの統合です。侵害がある場合は私に連絡してください。

おすすめ

転載: blog.csdn.net/hbhhhxs/article/details/105187494