【10】斐波那契数列的循环和递归实现

面试题10:斐波那契数列

【0】目录:

【1】题目
【2】分析
【3】测试代码
【4】测试结果
【5】算法优劣分析

【1】题目:

写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项。

斐波那契数列: 1,1,2,3,5,8,13,21,34,55,89 ……
这里写图片描述

【2】分析:

在斐波那契数列中,不难得出规律,当n > 2时,某个数等于前两位数之和,如: 2 = 1+ 1;3 = 1+ 2; 5 = 2 +3……
那么我们可以分为三个部分来求解,如下所示:
这里写图片描述

【3】测试代码:

#include<iostream>
using namespace std;
 //========================循环实现===============================
long long Fibonacci01(unsigned int n )
{
    int result[2]={0,1}; 
     if (n < 2)
        {
            return result[n];
         }
    long long fib1 = 0;
    long long fib2 = 1;
    long long fibn = 0;
    for(int i = 2; i<= n ;++i )
    {
        fibn = fib1+fib2;
        fib1 = fib2;
        fib2 =fibn;
    }
    return fibn;
}

//===========================递归实现================================
long long Fibonacci02(unsigned int n)
{
    if(n <= 0)
    {
        return 0;
    }
    if(n == 1)
    {
        return 1;
    }
    if(n >= 2)
        return Fibonacci02( n - 1)+Fibonacci02( n - 2) ;
}

//====================测试代码========================
void test()
{
    long long ret1 = 0,ret2 = 0 ;
    int  n = 0;
    printf("请输入待求斐波那契数的数:\n");
    scanf( "%d", &n );
    ret1 = Fibonacci01(  n );
    ret2 = Fibonacci02(  n ); 


    printf("循环实现第%d个斐波那契数ret1为: %lld\n",n, ret1);
    printf("递归实现第%d个斐波那契数ret2为: %lld\n",n, ret2);

}

int main()
{
    test();
    return 0;
}

【4】测试结果如下:

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

这里写图片描述

【5】算法优劣分析:

上面我们采用了循环和递归分别求第n个斐波那契数,那么这两种方式各有优缺点:
递归算法:
递归的本质是将一个难以解决的大问题分解成若干个小的模块,每个小模块再来求解;递归的底层是用栈来实现的;递归用来解决这个问题,显然是合适的;优点:代码量少,逻辑清晰、算法一目了然;缺点:在求斐波那契数列的时候,会大量的重复调用现象,如下图所示,( f ( 6 ) 计算了4次) 这些重复的操作会占用大量的时间,因此,当所求的斐波那契数过大时,效率不高,当输入40时,明显要等几秒,结果才会出来,当数字过大时,将无法计算;另外,在函数调用的时候,会开辟空间,而每个进程的栈容量都是有限的,这就容易造成栈溢出;显然,使用递归算法,那么,算法的时间复杂度O 是以n的指数的方式递增的;
这里写图片描述
循环算法:
只要递归能实现的地方,基本都可以通过循环实现,循环看似比较繁琐,但实际上,是最实用的一种方案,我们可以将已经得到的中间项保存起来,下次计算的时候,先查找一下,如果之前计算过了,就不再重复计算了,显然这种方法的时间复杂度为O(n)

猜你喜欢

转载自blog.csdn.net/dai_wen/article/details/79959399