朴素的实现是自然而优雅的,但在执行过程中递归调用正在创建二叉树。除了已经提到的记忆化、先前 F(n) 结果的兑现和避免不必要的树遍历之外,您还可以进行尾调用优化,已经提到了迭代或矩阵乘法。例如,Java 8 记忆:
private static final Map<Long, Long> memo = new HashMap<>();
static {
memo.put(0L, 0L);
memo.put(1L, 1L);
}
public static void main(String[] args) {
System.out.println(fibonacci(0));
System.out.println(fibonacci(43));
System.out.println(fibonacci(92));
}
public static long fibonacci(long n) {
return memo.computeIfAbsent(n, m -> fibonacci(m - 1) + fibonacci(m - 2));
}
或者也许是尾调用优化版本:
interface FewArgs<T, U, V, R> {
public R apply(T t, U u, V v);
}
static FewArgs<Long, Long, Long, Long> tailRecursive;
static {
tailRecursive = (a, b, n) -> {
if (n > 0)
return tailRecursive.apply(b, a + b, n - 1);
return a;
};
}
你用 a = 0, b = 1 来调用它,n 是第 n 个斐波那契数,但必须小于 93。计算斐波那契数的更有效方法是矩阵平方,你可以在我的博客上找到示例,以及 Binet 公式