最近在忙着学习redis的源代码,总算把《redis设计和实现》看完了,下面该详细写redis的代码分析了。好久木有更新算法题了,现在继续更新算法题,看一下题目:
第19题
题目:定义Fibonacci数列如下:
/ 0 n=0
f(n)= 1 n=1
\ f(n-1)+f(n-2) n=2
输入n,用最快的方法求该数列的第n项。
记得在遥远的7年多前,刚上大一学习C语言那会,谭浩强的那本绿皮C语言程序设计上有这个问题:当时是为了讲解递归,用的是这个例子来说明的。
那自然就想到用递归解决这个问题,但其实递归解决这个问题并不是好的办法。
可以画一棵递归树:
f(10)
/ \
f(9) f(8)
/ \ / \
f(8) f(7) f(7) f(6)
/ \ / \
f(7) f(6) f(6) f(5)
Ok,我们看到用递归树解决这个这个问题很笨,做了很多重复的计算:用递归解决这个问题的代码大概是这样的:
long recursionOfFibonacci(long n) {
if (2 < n ) {
return recursionOfFibonacci(n-1) + recursionOfFibonacci(n-2);
} else if(0 < n) {
return 1;
}
return 0;
}
看到递归树,我们大概就会想到用缓存把中间计算过程缓存下来,这样的代码页不难实现,大概是这样的:
// 时间复杂度是O(n)
long cacheOfFibonacci(long n) {
if (0 == n ) {
return 0;
} else if(1 == n || 2 == n) {
return 1;
}
long cache[2];
cache[0] = 1;
cache[1] = 1;
long tmp = 0;
// 时间复杂度是O(n)
for (long i = 3; i < n; i++) {
tmp = cache[1] + cache[0];
cache[1] = cache[0];
cache[0] = tmp;
}
return cache[0] + cache[1];
return 0;
}
本人呢,也比较笨,没有想到别的办法,网络上搜了一下看到有一种利用矩阵乘法把一维递推优化到O(lgn)的。OK,本人真是跪了,转一下这位大神的分析:
http://zhedahht.blog.163.com/blog/static/25411174200722991933440/
OKay,路漫漫…吾将上下而求索…