斐波纳契(Fibonacci)数列:
0, 1, 1, 2, 3, 5, 8, 13, 21…
以0和1开始,并且后面的每个斐波纳契数是前两个斐波纳契数之和。
斐波纳契数列可以递归定义:
Fibonacci(0)= 0
Fibonacci(1)= 1
Fibonacci(n)= Fibonacci(n-1) + Fibonacci(n-2)
使用递归算法的Java代码如下:
public long fibonacci(long n)
{
if(n==0||n==1)
return n;
else
return fibonacci(n-1) + fibonacci(n-2);
}
在这里有个有趣的问题:
假如计算fibonacci(3)时,会产生2个递归调用; fibonacci(2)和fibonacci(1)如下图:
进行简化如下:
从上图中可以清楚的看到使用递归算法计算fibonacci(3)一共进行了5次递归调用;
那么计算fibonacci(20)、fibonacci(30)、…又要递归多少次呢?
假如计算fibonacci(31)需要调用4356617次,计算fibonacci(32)需要7049155次,可以看出递归计算斐波那契数列,对函数的调用是爆炸式的,相邻的第31和32个斐波那契数就增长了664080次。
n | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
fibonacci(n) | 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 |
那么再列出fibonacci(4)的图
一共调用5+3+1=9次
n | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
fibonacci(n) | 0 | 1 | 1 | 2 | 3 6 | 5 19 | 8 | 13 | 21 | 34 |
次数count(n) | 1 | 1 | 3 | 5 | 9 | 15 | 25 | 41 | 67 | 109 |
红色字体为调用次数与计算fibonacci(n)的值之差。
可以得到差值和调用次数分别遵循如下斐波那契函数:
差值:
Difference (0) = 1
Difference (1) = 0
Difference (n) = Difference (n-1) + Difference (n-2) + 1
调用次数;
Count (0) = 1
Count (1) = 1
Count (n) = Count (n-1) + Count (n-2) + 1