斐波那契数列数列的三种时间复杂度的实现方法
来源:互联网 发布:《网络基础知识》文档 编辑:程序博客网 时间:2024/05/22 04:42
给定整数N,返回斐波那契数列的第N项
斐波那契数列为1,1,2,3,5,8,......也就是除第1项和第2项为1以外,对于第N项,有F(N)=F(N-1)+F(N-2),于是能够很轻松的写出暴力递归的代码。其时间复杂度为O(2^N).
int Fibonacci1(int n){ if(n<1)return 0; if(n==1 || n==2) return 1; return Fibonacci1(n-1)+Fibonacci1(n-2);}int main(){ int result = Fibonacci1(30); cout<<result<<endl; return 0;}
斐波那契数列也可以从左到右依次求出每一项的值,那么通过顺序计算求得第N项即可。其时间复杂度为O(N)。
int Fibonacci2(int n){ int tmp=0; int res=1; int pre=1; if(n<1)return 0; if(n==1 || n==2) return 1; for(int i=3;i<=n;i++) { tmp=res; res=res+pre; pre=tmp; } return res;}int main(){ int result = Fibonacci2(30); cout<<result<<endl; return 0;}
如果递归式严格遵循F(N)=F(N-1)+F(N-2),对于求第N项的值,有矩阵乘法的方式可以将时间复杂度降至O(logN)。F(N)=F(N-1)+F(N-2),是一个二阶递推数列,一定可以用矩阵乘法的形式表示,切状态矩阵为2*2的矩阵:
(F(N),F(N-1))=(F(N-1),F(N-2))*| {a,b},{c,d}|
把斐波那契数列的前4项带入可得:a=b=c=1;d=0
原公式可简化为:
(F(N),F(N-1))=(F(N-1),F(N-2))*| {1,1},{1,0}| = (1,1)*| {1,1},{1,0}|^(n-2)
求斐波那契数列第N项的问题就变成了如何用最快的方法求一个矩阵N次方的问题,而求矩阵N次方的问题明显是一个能够在O(logN)时间内解决的问题。为了表示方便,用求一个整数N次方的例子来说明,因为只要理解了如何在O(logN)的时间复杂度内求整数N次方的问题,对于求矩阵N次方的问题是同理的,区别是矩阵乘法和整数乘法在细节上有些不一样,但两者道理相同。
将设一个整数10,如何最快的求10的11次方
1. 11的二进制形式为1011.
2. 10的11次方=10^8 * 10^2 * 10^1。
在这个过程中,我们先求出10^1,然后根据10^1求出10^2,再根据10^2求出10^4,......,最后求出10^8,即11的二进制数形式总共多少位,就使用了几次乘法。
3. 在步骤2进行的过程中,把应该累乘的值相乘即可,比如10^8、10^2、10^1应该累乘,因为8,2,1对应到11的二进制数中,相应位上是1;而10^4不应该累乘,因为4对应到11的二进制数中,相应位上是0。
#include <iostream>#include<stdlib.h>using namespace std; struct matrix{ int m[2][2]; }ans; matrix mulimatrix(matrix &m1, matrix &m2){ matrix res0; for(int i=0; i<2; i++){ for(int j=0; j<2; j++){ res0.m[i][j]=0; for(int k=0; k<2; k++){ res0.m[i][j] += m1.m[i][k]*m2.m[k][j]; } } } return res0; } matrix matrixpower(matrix &mat, int p){ matrix tmp=mat; matrix res1; for(int i=0; i<2; i++){ res1.m[i][i]=1; } res1.m[0][1]=0; res1.m[1][0]=0; for( ; p != 0; p >>= 1){ if((p&1)!=0){ res1 = mulimatrix(res1,tmp); } tmp = mulimatrix(tmp,tmp); } return res1; } int Fibonacci(int n) { if(n<1)return 0; if(n==1 || n==2) return 1; matrix base = {1,1,1,0}; matrix res= matrixpower(base, n-2); int result= res.m[0][0] + res.m[1][0]; return result; }int main(){ int result = Fibonacci(30); cout<<result<<endl; return 0;}
- 斐波那契数列数列的三种时间复杂度的实现方法
- 斐波那契数列算法的三种C#实现及时间复杂度分析
- 斐波那契数列的三种解法及时间复杂度
- 实现斐波那契数列的三种方法
- 斐波那契数列 的三种实现方法
- 斐波那契数列实现的三种方法
- 斐波那契数列的三种实现方法
- 斐波那契数列的时间复杂度详释与改进方法
- 斐波那契数列的递归与非递归算法实现及其时间复杂度
- 斐波那契数列的三种实现方式
- 斐波那契数列-java编程:三种方法实现斐波那契数列
- 斐波那契数列-java编程:三种方法实现斐波那契数列
- 斐波那契数列的三种算法以及复杂度
- java实现斐波那契数列的几种方法时间效率问题
- 实现斐波那契数列的几种方法
- 斐波那契数列的两种实现方法
- 斐波那契数列的两种实现方法
- 关于斐波那契数列三种解法及时间复杂度分析
- Dijkstra+堆优化模板
- POJ1330Nearest Common Ancestors
- PHP生成缩略图
- QT问题系列(2)
- Beaglebone Black上使用Codesys开发EtherCAT(四)
- 斐波那契数列数列的三种时间复杂度的实现方法
- API学习Collections
- HDU2586How far away? LCA
- 数据库数据按指定格式导出到Excel
- 大学生活随笔
- <iframe>引用页面传值获取不到的问题
- FormData表单字段数据对象
- PHP 数组和字符串互相转换实现方法
- linux——文本处理——正则表达式