1、什么是斐波那契数?
斐波那契数,又称黄金分割数列、因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……
斐波那契数,通常用 F(n) 表示,形成的序列称为斐波那契数列。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0, F(1) = 1 F(N) = F(N - 1) + F(N - 2), 其中 N > 1. 给定 N,计算 F(N)。 2、经典解法-递归根据题意,我们可以用递归求解。
public int fib(int N) { if (N < 2) { return N; } return fib(N-1) + fib(N-2); }但是这个是最好的解法吗?
假如我们要计算的N为10,我们要先计算fib(9),再计算fib(8);
计算fib(9), 要计算fib(8)和fib(7),如此递归下去
计算fib(8), 要计算fib(7)和fib(6),如此递归下去
发现什么问题没?
越往小了算,重复计算越多, 时间效率n的n次方,不可想象
fib(30)耗时 4毫秒
fib(50)耗时 62秒
fib(100)耗时(1h没结果,停了)
那有没有其它的好办法呢?
你发现没有我们用递归是从大到小计算,从fib(N)到fib(N-1)...fib(0)
但是我们fib(N)不知道结果,我们只知道fib(0)和fib(1)
我们可不可以试着从小到大计算
3、动态规划我们尝试从小往大推演,把计算结果保存下来,避免重复计算,这种方法一般称之为动态规划。
public int fib(int N) { if (N < 2) { return N; } int[] cache = new int[N+1]; cache[0] = 0; cache[1] = 1; for (int i = 2; i <= N; i++) { cache[i] = cache[i-1] + cache[i-2]; } return cache[N]; }上面的代码: cache[i] = cache[i-1] + cache[i-2]称之为动态规划公式
时间效率n, 遍历一次即可
空间效率n,缓存n个数据
空间效率还可以改进
4、动态规划改进我们用m代表fib(n-2), n代表fib(n-1), o代表fib(n)
每次计算结束再重置 m 和 n
public int fib(int N) { if (N < 2) { return N; } int m = 0, n = 1; for (int i = 2; i <= N; i++) { int o = n + m; m = n; n = o; } return n; }时间效率n, 遍历一次即可
空间效率3
还有一种数学解法,有兴趣的可以自己去了解