zoukankan      html  css  js  c++  java
  • 斐波那契数列的递归,迭代(循环),通项公式三种实现

    谓Fibonacci数列是指这样一种数列,它的前两项均为1,从第三项开始各项均为前两项之和。用数学公式表示出来就是:
               1                            (n=1,2)
    fib(n)=
               fib(n-1)+fib(n-2)     (n>2)
    可以证明斐波那契数列的通项公式为fib(n) = [(1+√5)/2]^n /√5 - [(1-√5)/2]^n /√5 (n=1,2,3.....),关于斐波那契数列的详细介绍请参阅百度百科
    下面我将介绍三种比较常用的求解第n项斐波那契数列的方法:递归法、迭代法、通项公式法。
    1、递归法
    这种方法的优点是简洁和容易理解,缺点是时间复杂度太大,随着n的增大,运算时间将会急剧增加。因此在很多场合这种方法是不可取的。
    使用这种方法的关键代码是:
    if(n == 1|| n== 2)
    {
        return 1;
    }
    else
    {
        return fib(n - 1) + fib(n - 2);
    }
    2、迭代法
    这种方法相对于递归法来说在时间复杂度上减小了不少,但代码相对就要复杂些了。它的思想是这样的,假设开始时f0=1,f1=1,currentFib表示当前斐波那契数,则:
    for(i = 1;i < n;i++)
    {
        currentFib = f0 + f1;
        f0 = f1;
        f1 = currentFib;
    }
    这样迭代结束和currentFib就是fib(n)了。
    3、通项公式法
    这种方法是最没技术含量的方法,只要你知道通项公式照着把它翻译成编程语言就可以了,优点不言而喻。
    fib(n) = pow(((1 + sqrt(5)) / 2.0),n) / sqrt(5) - pow(((1 - sqrt(5)) / 2.0),n) / sqrt(5));
    小结:
    这三种方法各有优缺点,使用哪种方法根据实际情况确定,从时间复杂度上来说O(通向公式法)<O(迭代法)<O(递归法)。
    下面我做了一个简单的测试:分别测试这三种方法计算0-30这31个斐波那契数所用的总时间。从测试结果看,递归确实很费时,特别是n在30以后计算起来就很费时了,而另外两种方法计算这31个斐波那契数所费时间基本为0。当然结果不会很准确,但至少能说明问题。
    测试代码:
    ************************************************************************************************************************************
    #include <stdio.h>
    #include <math.h>
    #include <time.h>
    #define ROOT_OF_FIVE sqrt(5.0)
    long double fib1(int n);
    //使用递归
    long double fib2(int n);
    //使用迭代
    long double fib3(int n);
    //使用通项公式
    int main()
    {
        int i;
        long double result1[31],result2[31],result3[31],consume[3],start,finish;
        printf("N           递归法          迭代法          通项公式法\n");
       
        start = (long double)clock();
        for(i = 0;i <= 30;i++)
        {   
            result1[i] = fib1(i);
        }
        finish = (long double)clock();
        consume[0] = finish - start;

        start = (long double)clock();
        for(i = 0;i <= 30;i++)
        {   
            result2[i] = fib2(i);
        }
        finish = (long double)clock();
        consume[1] = finish - start;

        start = (long double)clock();
        for(i = 0;i <= 30;i++)
        {   
            result3[i] = fib3(i);
        }
        finish = (long double)clock();
        consume[2] = finish - start;

        for(i = 0;i <= 30;i++)
        {
            printf("%02d          %06.0lf          %06.0lf          %06.0lf\n",i,result1[i],result2[i],result3[i]);
        }
        printf("Total time: %lfms    %lfms      %lfms\n",consume[0],consume[1],consume[2]);
        return 0;
    }
    ===============================================================================================================
    long double fib1(int n)
    {//使用递归
        if(n == 0)
        {
            return 0;
        }
        else if(n == 1)
        {
            return 1;
        }
        else
        {
            return fib1(n - 1) + fib1(n - 2);
        }
    }

    long double fib2(int n)
    {//使用迭代
        if(n == 0)
        {
            return 0;
        }
        else if(n == 1)
        {
            return 1;
        }
        else
        {
            long double f0 = 0,f1 = 1,currentFib;
            int i;
            for(i = 1;i < n;i++)
            {
                currentFib = f0 + f1;
                f0 = f1;
                f1 = currentFib;
            }
            return currentFib;
        }
    }

    long double fib3(int n)
    {//使用通项公式Fib(n) = [(1+√5)/2]^n /√5 - [(1-√5)/2]^n /√5
        return (pow(((1 + ROOT_OF_FIVE) / 2.0),n) / ROOT_OF_FIVE -
            pow(((1 - ROOT_OF_FIVE) / 2.0),n) / ROOT_OF_FIVE);
    }
  • 相关阅读:
    bzoj1415 NOI2005聪聪和可可
    Tyvj1952 Easy
    poj2096 Collecting Bugs
    COGS 1489玩纸牌
    COGS1487 麻球繁衍
    cf 261B.Maxim and Restaurant
    cf 223B.Two Strings
    cf 609E.Minimum spanning tree for each edge
    cf 187B.AlgoRace
    cf 760B.Frodo and pillows
  • 原文地址:https://www.cnblogs.com/fhuafeng/p/1456661.html
Copyright © 2011-2022 走看看