递归解斐波那契数列
斐波那契数列最直观的递归解法:
int fib(int n){
if (n<2) {
return n;
} else {
return fib(n-1) + fib(n-2);
}
}
然而这种解法效率很低,会进行很多重复运算
例如:当计算 fib(5) 时,我们共需要计算1次 fib(4),2次 fib(3),3次 fib(2),5次 fib(1) 和3次 fib(0)。这些无意义的重复计算使得递归效率极低。
递归解法的优化
实际上像斐波那契这样的数列还有很多,他们都满足相同的规律,即从第三项开始,每一项等于前两项之和。这样的数列被统称为可加数列(additive sequence),不同的只是他们的第一项 t0 和 t1。
斐波那契数列:
0
,
1
,
1
,
2
,
3
,
5
,
8
,
13
,
21
,
34
,
55
,
…
0, 1, 1, 2, 3, 5, 8,13,21, 34,55,\dots
0,1,1,2,3,5,8,13,21,34,55,…
如果我们将它的第一项和第二项换成3和7,就会变成:
3
,
7
,
10
,
17
,
27
,
44
,
71
,
115
,
186
,
…
3, 7, 10, 17, 27, 44, 71,115,186, \dots
3,7,10,17,27,44,71,115,186,…
因此,求解斐波那契数列第n项的问题可以被转化成求解一个可加数列的第n项的问题,而且只需要知道 t0 和 t1 的值,我们就可以求出数列中的任意一项。所以我们可以写出一个函数:
int additiveSequence(int n, int t0, int t1);
下一步就是实现这个函数。继续观察可加数列,我们可以发现一个可加数列S中的第n项等于将这个数列每一项都向前移一位的新数列的第n-1项。
例如,原数列中的t6 = 71:
当我们将该数列每一位都向前移动一位,得到一个新数列,此时 t5 = 71:
而这个新的 t0 等于原数列的 t1,新的 t1 等于原数列的 t0 + t1。
因此函数可以写为:
int additiveSequence(int n, int t0, int t1){
if (n==0) return t0;
if (n==1) return t1;
return additiveSequence(n-1, t1, t0+t1);
}
递归求解斐波那契数列的完整函数就可写为:
int fib(int n){
return additiveSequence(n, 0, 1);
}
int additiveSequence(int n, int t0, int t1){
if (n==0) return t0;
if (n==1) return t1;
return additiveSequence(n-1, t1, t0+t1);
}