斐波那契数列求解

【斐波那契数列】
 fibonacci数列,斐波那契数列,又称黄金分割数列。
在数学上,费波那西数列是以递归的方法来定义:
  • F_0=0
  • F_1=1
  • F_n = F_{n-1}+ F_{n-2}
用文字来说,就是费波那西数列由 0 和 1 开始,之后的费波那西系数就由之前的两数相加。
特别指出:0不是第一项,而是第零项
 
通项公式:a_{n}=\frac{\sqrt{5}}{5} \cdot \left[\left(\frac{1 + \sqrt{5}}{2}\right)^{n} - \left(\frac{1 - \sqrt{5}}{2}\right)^{n}\right]

 
 
【求解斐波那契数列】
解法一:递归求解
对于求解斐波那契数列,最直接的方法就是根据定义用递归方法来实现。但是这种方法算法复杂度高(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[n];
         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[n];
         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项的值。
 
 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值