求斐波那契数,你还在用递归吗?

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

还有一种数学解法,有兴趣的可以自己去了解

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpzgjx.html