斐波那契数列求解
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;
}
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项的值。
相关文章推荐
- 3种方法求解斐波那契数列
- 二分法求解超大项的斐波那契数列数值
- VJ水题堆-关于斐波那契数列的求解过程
- 第12周项目3-用递归函数求解--斐波那契数列
- Java算法--递推算法 求解兔子产子问题或斐波那契数列问题
- 用python快速求解斐波那契数列的某一项
- 动态规划入门之求解斐波那契数列
- 用递归,迭代,通项公式三种方法实现斐波那契数列求解
- 求解斐波那契数列的第n项
- 斐波那契数列的递归与非递归求解方法&递归的优缺点
- 求解斐波那契数列
- 基于特征值的斐波那契数列求解
- 【算法02】3种方法求解斐波那契数列
- 求解斐波那契数列的第n个数
- 矩阵快速幂求解任意初始值f1,f2及a,b的斐波那契数列
- 斐波那契数列的几种求解方法
- 求解斐波那契数列的第n个数
- 第十二周项目3-用递归的方法求解(斐波那契数列)
- 求解斐波那契数列第100位(Java BigInteger版本)
- 递归求解斐波那契数列