首页 > 代码库 > 算法学习-第0篇 从Fibonacci开始

算法学习-第0篇 从Fibonacci开始

学习资源《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)。
③算法能否改进?
答:性能已为线性,可不再改进。

算法学习-第0篇 从Fibonacci开始