是的,您的见解是正确的。
这称为dynamic programming。这通常是一种常见的内存运行时权衡。
在 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) 的精确数学公式。它包含这些特征值的幂,因此复杂度仍然是对数的。
斐波那契波经常被拿来作为例子来说明动态规划,但正如你所见,它并不是很贴切。
@约翰:
我认为这与哈希无关。
@约翰2:
地图有点笼统,你不觉得吗?对于 Fibonacci 案例,所有键都是连续的,因此向量是合适的,再次有更快的方法来计算 fibo 序列,请参阅我的代码示例。