是的,您的见解是正确的。这称为动态规划。这通常是一种常见的内存运行时权衡。
在 fibo 的情况下,您甚至不需要缓存所有内容:
[编辑]该问题的作者似乎正在寻找一种通用的缓存方法,而不是一种计算斐波那契的方法。搜索维基百科或查看其他海报的代码以获得此答案。这些答案在时间和记忆上是线性的。
**这是一个线性时间算法 O(n),在内存中是常数 **
in OCaml:
let rec fibo n =
let rec aux = fun
| 0 -> (1,1)
| n -> let (cur, prec) = aux (n-1) in (cur+prec, cur)
let (cur,prec) = aux n in prec;;
in C++:
int fibo(int n) {
if (n == 0 ) return 1;
if (n == 1 ) return 1;
int p = fibo(0);
int c = fibo(1);
int buff = 0;
for (int i=1; i < n; ++i) {
buff = c;
c = p+c;
p = buff;
};
return c;
};
这在线性时间内执行。但是日志实际上是可能的!Roo 的程序也是线性的,但速度较慢,并且使用内存。
这是对数算法 O(log(n))
现在对于日志时间算法(方式方式更快),这里有一个方法:如果你知道 u(n),u(n-1),计算 u(n+1),u(n) 可以通过应用矩阵:
| u(n+1) | = | 1 1 | | u(n) |
| u(n) | | 1 0 | | u(n-1) |
这样你就有了:
| u(n) | = | 1 1 |^(n-1) | u(1) | = | 1 1 |^(n-1) | 1 |
| u(n-1) | | 1 0 | | u(0) | | 1 0 | | 1 |
计算矩阵的指数具有对数复杂度。只需递归地实现这个想法:
M^(0) = Id
M^(2p+1) = (M^2p) * M
M^(2p) = (M^p) * (M^p) // of course don't compute M^p twice here.
您也可以将其对角化(不难),您会在其特征值中找到黄金数及其共轭,结果将为您提供 u(n) 的精确数学公式。它包含这些特征值的幂,因此复杂性仍然是对数的。
Fibo 经常被拿来作为例子来说明动态规划,但正如你所看到的,它并不是真正的中肯。
@John:我认为这与哈希无关。
@John2:你不觉得地图有点笼统吗?对于斐波那契案例,所有键都是连续的,因此向量是合适的,再次有更快的方法来计算斐波那契序列,请参阅我的代码示例。