您的位置:首页 > 其它

斐波那契数列求解

2013-11-18 16:11 162 查看
【斐波那契数列】

 fibonacci数列,斐波那契数列,又称黄金分割数列。

在数学上,费波那西数列是以递归的方法来定义:

用文字来说,就是费波那西数列由 0 和 1 开始,之后的费波那西系数就由之前的两数相加。
特别指出:0不是第一项,而是第零项。
 
通项公式:


(推导方法见维基百科:http://zh.wikipedia.org/wiki/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97

 
 
【求解斐波那契数列】
解法一:递归求解
对于求解斐波那契数列,最直接的方法就是根据定义用递归方法来实现。但是这种方法算法复杂度高(n的指数级别),效率低。由于递归方法中存在着大量的重复计算,当n较大时,计算量将特别大。




//递归方法求解
long fib_recursion( int n )

{

    if( n==0 ) return 0;

    if( n==1 ) return 1;

    return fib_recursion(n-1) + fib_recursion(n-2);

}

 
解法二:开辟n+1的数组
为了避免重复计算,我们可以采用数组来存储已经计算过的数值,避免重复计算。这样算法的时间复杂度大大降低,变为O(n).缺点是要动态开辟数组,空间复杂度较高。


//开辟数组求解
long fib_mem( int n )

{

    if(n<=0)

        return 0;

    else if(n==1)

        return 1;

    else

    {

        //动态创建一个长度为(n+1)的数组

        int *arry=new int[n+1];

        arry[0]=0;

        arry[1]=1;

        for(int i=2;i<=n;i++)

        {

            arry[i]=arry[i-1]+arry[i-2];

        }

        int result=arry
;

        delete [] arry;//释放空间

        return result;

    }

}

 
解法三:动态规划,设置临时变量保存上一步计算的数值
设置两个临时变量保存f(n-1)和f(n-2)的值,这样时间复杂度为O(n),空间复杂度为O(1)


//动态规划
int fib_dp( int n )

{

    long first = 0;

    long second = 1;

    int sum ;

 

    for ( int i=0; i<n-1; ++i)

    {

        sum = first + second;

        first = second;

        second = sum;

    }

    return sum;

}

 
解法四:公式法
利用fibonacci的一般表达式,我们可以直接求解。这是最快的方法,复杂度为O(1)。


//公式法求解
int fib_binet( int n)

{

    return ( pow( (1+pow(5,0.5)),n
) - pow( (1-pow(5,0.5)),n ))/(pow(2.0,n)*pow(5,0.5));

}

 
完整代码


#include <iostream>

#include <time.h>

#include <math.h>
using namespace std;

 
//递归求解
int fib_recursion( int n )

{

 

    if( n==0 ) return 0;

    if( n==1 ) return 1;

 

    return fib_recursion(n-1) + fib_recursion(n-2);

}

 
//使用数组存放数列中的每一个值
int fib_mem( int n )

{

    if(n<=0)

        return 0;

    else if(n==1)

        return 1;

    else

    {

        //动态创建一个长度为(n+1)的数组

        int *arry=new int[n+1];

        arry[0]=0;

        arry[1]=1;

        for(int i=2;i<=n;i++)

        {

            arry[i]=arry[i-1]+arry[i-2];

        }

        int result=arry
;

        delete [] arry;//释放空间

        return result;

    }

}
//动态规划
int fib_dp( int n )

{

    long first = 0;

    long second = 1;

    int sum ;

 

    for ( int i=0; i<n-1; ++i)

    {

        sum = first + second;

        first = second;

        second = sum;

    }

    return sum;

}
//binet给出了一个公式可以计算数列,比任何动态规划算法都快,但是这样的公式可欲不可求
int fib_binet( int n)

{

    return ( pow( (1+pow(5,0.5)),n
) - pow( (1-pow(5,0.5)),n ))/(pow(2.0,n)*pow(5,0.5));

}
//测试代码
int main()

{

    int n ;

    cout<<"请输入要求解的fibonacci数"<<endl;

    cin>>n;

 

    clock_t timebegin, timeend;

 

    timebegin = clock();

    int sum_recursion = fib_recursion(n);

    timeend = clock();

    cout << "sum_recursion = " << sum_recursion << "  用时" <<timeend-timebegin << endl;

 

    timebegin = clock();

    int sum_mem = fib_mem(n);

    timeend = clock();

    cout << "sum_mem = " << sum_mem << "  用时" <<timeend-timebegin << endl;

 

    timebegin = clock();

    int sum_dp = fib_dp(n);

    timeend = clock();

    cout << "sum_dp = " << sum_dp << "  用时" <<timeend-timebegin << endl;

 

    int sum_binet = fib_binet(n);

    cout << "sum_binet= " << sum_binet <<endl;

 

    return 0;

}

 
 
 
【斐波那契数列应用实例】

1.一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个n级的台阶总共有多少种跳法。

解题思路:此题本质上就是求解fibonacci数列第n项的值。若n=1,则f(1)=1;若n=2,则f(2)=2;若n=3,可以这样考虑青蛙若最后一跳可以跳一级,则方法为数为f(2),若最后一跳跳2级,则方法数为f(1),因此f(3)=f(1)+f(2)。所以当n>=3时,f(n)=f(n-1)+f(n-2);所以本题就是求解fibonacci数列第n项的值。

 
 
                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息