学习资源《Algorithms》,作者S.Dasgupta,C.H.Papadimitriou,and U.V.Vazirani。
电子版可到资源库中下载http://download.csdn.net/detail/segen_jaa/7900765。
1、问题描述
Fibonacci数列想必大家都比较熟悉,后一位数字是前两位的和。
0,1,1,2,3,5,8,13,21,34
对应公式如下。
求第n位的Fibonacci数为多少?
2、迭代算法
实现语言:C语言。
win32程序下,计算Fibonacci数。
45位:1134903170
46位:1836311903
47位:-1323752223
计算到第47位long型已经不支持,故测试程序约定在50位以内。
#include "stdafx.h" #define MAX_NUM 50 long fib1(int n) { if (0 == n) return 0; if (1 == n) return 1; return fib1(n-1)+fib1(n-2); } int _tmain(int argc, _TCHAR* argv[]) { while(true) { int input = 0; printf("please input fibonacci number:"); scanf("%d", &input); if (input>MAX_NUM) { printf("please input number less than %d", MAX_NUM); continue; } if (input<0) { break; } int result1 = fib1(input); printf("fib1 result:%d\n", result1); } return 0; }
3、迭代算法分析
三个问题
①算法是否正确?
②算法复杂度多少?
③算法能否改进?
对应回答:
①实现完全按照定义公式,正确性没有疑问。
②看到递归,大家应该都知道了,这个算法时间复杂度有点高。
一次加减操作复杂度都为1,那么T(n)=T(n-1)+T(n-2)+3。
经过计算T(n)值≈
出现指数计算法,那么这个算法可以宣告失败了。这意味着计算机性能每提高1.6倍,只往前多计算出一位。
在这种算法下,大家可以在自己机器上试一下计算要多久。本机cpu i7测试,推算第50位接近1小时时间。如果要同样时间计算出第51位,只能等到i8、i9了。
③若要对算法进行改进,则首先分析为何复杂度如此高。
递归调用的过程如下。
可以看到同一个数被重复计算了多次。以F(n-3)为例,在下图中被计算了三次。那么我们的改进思路就从这里入手,已计算过的数字就缓存起来。
4、改进算法
#include "stdafx.h" #define MAX_NUM 50 long fib2(int n) { long array[MAX_NUM]; array[0] = 0; array[1] = 1; for (int i=2; i<=n; ++i) { array[i] = array[i-1]+array[i-2]; } return array[n]; } int _tmain(int argc, _TCHAR* argv[]) { while(true) { int input = 0; printf("please input fibonacci number:"); scanf("%d", &input); if (input>MAX_NUM) { printf("please input number less than %d", MAX_NUM); continue; } if (input<0) { break; } int result2 = fib2(input); printf("fib2 result:%d\n", result2); } return 0; }
同样的问题
①算法是否正确?
答:正确。
②算法复杂度多少?
答:复杂度O(n)。
③算法能否改进?
答:性能已为线性,可不再改进。