斐波那契数列的递归与循环实现及复杂度分析

         目录

一、斐波那契数列的定义

二 、递归实现

三、循环实现

四、补充


一、斐波那契数列的定义

斐波那契数列的递归与循环实现及复杂度分析_第1张图片

二 、递归实现

经典例题(杭电2041):

斐波那契数列的递归与循环实现及复杂度分析_第2张图片

 AC代码:

#include 

using namespace std;
int f[41];

int main(){
    int num,m;
    cin >> num;
    while(num--){
        f[1] = 1;
        f[2] = 1;
        for(int i = 3;i < 41;i++){
            f[i] = f[i-1] + f[i-2];
        }
        cin >> m;
        cout << f[m] << endl;
    }
    return 0;
}

 复杂度分析(以 \large n = 6 为例):

斐波那契数列的递归与循环实现及复杂度分析_第3张图片

  • 注意计算复杂度规则:关注最高次数项,忽略常数与系数
  • 时间复杂度:为二叉树的所有节点个数
    • 在本例中,二叉树的高度 h5
    • 图中共有 15 个节点,即 1 + 2 + 4+8=15,可以理解为 2^{0}+2^{1}+2^{2}+2^{3} = 15,也就是层数为 4 的满二叉树( 2^{h}-1,h=4
    • F(6) 的层数为 4 层, 则  F(n)n-2 层,所有节点个数为 2 ^ {n-2}- 1 = (\frac{2 ^ n}{4})-1,忽略常数与系数,则为 2^{n}
    • 时间复杂度为 O(2^{N})
  • 空间复杂度为树的高度:h 即 O(N)

分析:递归实现的代码简洁易懂,但是需要注意的是,递归由于是函数调用自身,而函数调用是有时间和空间的消耗的,每一次函数调用,都需要在内存栈中分配空间以保存参数、返回地址及临时变量,而往栈里压入数据和弹出数据都需要时间,因而递归实现的效率不如循环。 

 三、循环实现

#include
int main()
{
    int a = 0, b = 1, n = 5;
    for(int i = 2;i <= n;i++){
        int t = b;
        b = a + b;
        a = t;
    }
    printf("%d\n", b);
    return 0;
}

时间复杂度:O(N),空间复杂度:O(1)。

四、补充

复杂度O符号表示取上界,Ω表示取下界,Θ当且仅当O() = Ω()时成立。

对于下列题目:

Θ(Fn)中的Fn表示时间复杂度与Fn的取值有关,事实上,时间复杂度只与我们求的是第几项有关,而与第几项的取值无关。

常用时间复杂度所耗费的时间从小到大依次是

O(1)<  O(logN) < O(N) < O(NlogN) < O(N^2) < O(N^3) < O(2^N) < O(N!)  <  O(N^N)

你可能感兴趣的:(C/C++,算法/数据结构)