zoukankan      html  css  js  c++  java
  • 算法题003 斐波那契(Fibonacci)数列

     

    斐波那契(Fibonacci)数列

    题目来源

      斐波那契(Fibonacci)数列是经典的递推关系式定义的数列。

      第一项是0,第二项是1,之后的每一项都是前面两项之和。

      

      POJ3070:http://poj.org/problem?id=3070

      九度剑指Offer:http://ac.jobdu.com/problem.php?cid=1039&pid=3

     

    递归的方法:低效

      用递归的方法解斐波那契数列的第n项的值是很直观的做法,因为斐波那契数列的定义就是这种递推的形式。

    //用递归的方法求解Fibonacci数列
    int Fibonacci(int n)
    {
        if(n <= 0)
        {
            return 0;
        }
        else if (n == 1)
        {
            return 1;
        }
        else
        {
            return Fibonacci(n - 1) + Fibonacci(n - 2);
        }
    
    }

      但是,递归的方法不是一种很好的解法,有很严重的效率问题

      比如,计算F[5],需要计算F[4]和F[3],而计算F[4]的时候又要计算F[3],所以存在很多结点的重复计算。

      像是一颗二叉树,父结点为左右结点之和,那么为了求根节点上的F[n],就要求它的左右结点F[n-1]和 F[n-2],而这两个结点的求法和根节点相同,这样扩展下去,当n较大时,计算量会急剧增大。

     

    递推关系式的优化:保存数列中间项,避免重复计算

      为了减少重复的计算,可以用一个数组储存所有已计算过的项

      这样便可以达到用空间换取时间的目的。

      在这种情况下,时间复杂度为O(n),而空间复杂度也为O(n)。

      

      这样做的好处在需要多次计算f(n)时更加有利

      比如已经计算过了f(100),那么就表明f(100)之前的结果都已经计算出来并保存了,第二次想要计算f(50)时,直接查询即可得到。

      代码如下,在九度上提交AC(http://ac.jobdu.com/problem.php?cid=1039&pid=3)。

      

    #include "stdafx.h"
    #include <iostream>
    using namespace std;
    
    int Fibonacci(int n);
    
    int main(int argc, char* argv[])
    {
        int n = 0;
    
        long fibonacci[1000]; 
        int count = 0;//保存数列已经计算了多少
    
    
        //先设定起始条件
        fibonacci[0] = 0;
        fibonacci[1] = 1;
        count = 1;
    
        while(cin>>n)
        {
    
            //递归算法
            //cout << Fibonacci(n) << endl;
    
    
            //非递归算法
            //因为要多次计算f(n),所以保存这个数列可进一步提高效率
            if(n > count)
            {
                for(int i = count + 1; i <= n; ++i)
                {
                    fibonacci[i] = fibonacci[i-1] + fibonacci[i-2];
                }
    
                cout << fibonacci[n] << endl;
    
            }
            else
            {
                //如果n小于等于count,则表明f(n)已经计算出来并且存储在相应的位置上了
                cout << fibonacci[n] << endl;
            }
    
    
        }
    
    
        return 0;
    }
    
    //用递归的方法求解Fibonacci数列
    int Fibonacci(int n)
    {
        if(n <= 0)
        {
            return 0;
        }
        else if (n == 1)
        {
            return 1;
        }
        else
        {
            return Fibonacci(n - 1) + Fibonacci(n - 2);
        }
    
    }

      需要注意的是,开始的时候我用的是int类型数组,所以总是无法通过,因为测试用例的数字已经超过了整形的表示范围。

    其他优化方法

      《编程之美》中还提到了其他优化方法:

      求解通项公式;

      使用分治策略,求解矩阵的方幂。

     

    参考资料

      《剑指Offer》

      《编程之美》

      Online Judge:

      POJ3070:http://poj.org/problem?id=3070

      九度剑指Offer:http://ac.jobdu.com/problem.php?cid=1039&pid=3

      相关解答博客:http://www.cnblogs.com/CCBB/archive/2009/04/25/1443441.html

     

     

  • 相关阅读:
    面向接口程序设计思想实践
    Block Chain Learning Notes
    ECMAScript 6.0
    Etcd Learning Notes
    Travis CI Build Continuous Integration
    Markdown Learning Notes
    SPRING MICROSERVICES IN ACTION
    Java Interview Questions Summary
    Node.js Learning Notes
    Apache Thrift Learning Notes
  • 原文地址:https://www.cnblogs.com/mengdd/p/2953315.html
Copyright © 2011-2022 走看看