算法习题19:Fibonacci数列深入
来源:互联网 发布:小米5s plus 知乎 编辑:程序博客网 时间:2024/05/21 17:04
/ 0 n=0
f(n)= 1 n=1
\ f(n-1)+f(n-2) n=2
输入n,用最快的方法求该数列的第n项。
——————————————————————————————
这个题目大家很熟悉,就是Fibonacci数列,大家第一个想到的就是递归方法,是的,这个我们学数据结构算法的时候用的就是这个方法,代码精简漂亮,可是有没有想过时间和空间上的开销呢?首先这是一个递归,空间上开销不用说,栈会不断积累,时间,当我们计算F(n-1)时候计算了F(n-2),可是递归没有记忆功能,所以计算F(n-2)还是在来一次,这就造成了时间复杂度的上升应该是O(n2)
(1)循环
所以这里稍微改进下,首先,递归一般都可以采用非递归方式实现,这里我们用循环来实现
long Fibonacci1(long input){long a0 = 1;long a1 = 1;long sum = 0;int i = 0;if(input <2)return 1;for(i=2;i<=input;i++){sum = a0+a1;a0 = a1;a1 = sum;}return sum;}
其实代码不难,重要的是思路把,
后来我上网搜了下大家对这道题的看法,有人提出了更巧妙的方式,循环的时间复杂度我们知道就是O(N)似乎已经很好了,不过还有O(logN)的方法
(2)矩阵
大家可以计算下
| 1 1 |
| 1 0 |
这个矩阵的n次方的规律,我们发现,刚好就是
|f(n-1)+f(n-2) f(n-1) |
|f(n-1) f(n-2) |
所以这道题就可以转换成矩阵求幂了。
可以A^n还是需要计算n次啊,我们可以利用平方的性质 [A^(n/2)}^2 = A^n 所以以此类推 那就是logN的复杂度了 不过要注意奇数偶数的幂
偶数 A^n = [A^(n/2)}^2
奇数 A^n = [A^((n-1)/2)}^2*{1,1,1,0}
long Fibonacci3(int input){long arr[4] = {1,1,1,0};long* result = F3(arr, input);return result[0];}long* F3(long* arr, int input){long arr1[4], arr2[4];long* temp1 = arr1;long* temp2 = arr2;if(input == 1){temp1[0] = 1;temp1[1] = 1;temp1[2] = 1;temp1[3] = 0;return temp1;}if(input == 2){//求得平方temp1[0] = arr[0]*arr[0] + arr[1]*arr[2];temp1[1] = arr[0]*arr[1] + arr[1]*arr[3];temp1[2] = arr[2]*arr[0] + arr[3]*arr[2];temp1[3] = arr[2]*arr[1] + arr[3]*arr[3];return temp1;}else{if(input%2 == 0){temp1 = F3(arr, input/2);temp2[0] = temp1[0]*temp1[0] + temp1[1]*temp1[2];temp2[1] = temp1[0]*temp1[1] + temp1[1]*temp1[3];temp2[2] = temp1[2]*temp1[0] + temp1[3]*temp1[2];temp2[3] = temp1[2]*temp1[1] + temp1[3]*temp1[3];return temp2;}else{temp1 = F3(arr, (input-1)/2);temp2[0] = temp1[0]*temp1[0] + temp1[1]*temp1[2];temp2[1] = temp1[0]*temp1[1] + temp1[1]*temp1[3];temp2[2] = temp1[2]*temp1[0] + temp1[3]*temp1[2];temp2[3] = temp1[2]*temp1[1] + temp1[3]*temp1[3];temp1[0] = temp2[0] + temp2[1];temp1[1] = temp2[0] ;temp1[2] = temp2[2] + temp2[3];temp1[3] = temp2[2] ;return temp1;}}cout<<"NULL??";return NULL;}
参见:http://blog.csdn.net/yuucyf/article/details/6625301
(3)递归
为了比较,这里还是把老式方法给出来
long Fibonacci2(long input){if(input < 2)return 1;elsereturn Fibonacci2(input-1)+Fibonacci2(input-2);}
我这里为了不让数列数太大,我循环执行,为了比较效率
long Fibonacci1(long input);long Fibonacci2(long input);long Fibonacci3(int input);long* F3(long* arr, int input);int main() {long input = 0l;cin>>input;int i =0;long result;clock_t start,end; //循环方法cout<<endl<<"循环:"<<endl;start = clock();for(i=0;i<3000000;i++)result = Fibonacci1(input);cout<<result;end = clock();cout<<endl<<(double)(end-start)/CLOCKS_PER_SEC; //老式递归cout<<endl<<"递归:"<<endl;start = clock();for(i=0;i<3000000;i++)result = Fibonacci2(input);cout<<result;end = clock();cout<<endl<<(double)(end-start)/CLOCKS_PER_SEC; //举证方法cout<<endl<<"矩阵:"<<endl;start = clock();for(i=0;i<3000000;i++)result = Fibonacci3(input);cout<<result;end = clock();cout<<endl<<(double)(end-start)/CLOCKS_PER_SEC;return 0;}
输出比较
13循环:3770.18s递归:3779.68s矩阵:3770.26s我们看到,老式的递归将近10秒了,由于输入10较小所以矩阵的速度无法充分体现出来,这里递归影响较大
我们看到,当输入求50的时候,时间就差开啦
50循环:203650110740.71s矩阵:203650110740.38s
- 算法习题19:Fibonacci数列深入
- Fibonacci数列问题算法
- Fibonacci数列 算法
- Fibonacci 数列算法
- 算法之数列 Fibonacci
- Fibonacci数列-递归算法
- Fibonacci数列算法分析
- fibonacci数列的矩阵算法
- 每日一算法:Fibonacci数列
- 经典算法之Fibonacci数列
- 算法基础:递归---Fibonacci数列
- 蓝桥杯算法 入门 Fibonacci数列
- Fibonacci数列算法Java版
- 网易算法题--Fibonacci数列
- 19、Fibonacci数列探秘
- Linux C一站式学习习题答案5.3.2Fibonacci数列
- 循环结构_习题:输出Fibonacci数列前20项
- 算法-java 递归中的Fibonacci数列
- 64位Win7系统WMware安装Mac OS
- Symmetric Tree 对称镜像树 @LeetCode
- 64位Ubuntu下下载编译Android4.3源码
- iphone 开发 --。。。
- android 通过文件路径,判断文件大小
- 算法习题19:Fibonacci数列深入
- SQL Server2008创建用户时,出现错误,解决办法
- vim 常用快捷键
- snmp错排除
- Eclipse将引用了第三方jar包的Java项目打包成jar文件的两种方法
- Magento My Orders里面不显示订单
- android 解析xml -XmlPullParser
- 作为项目经理来谈谈需求评审
- 浅谈C++多态性