《学习JavaScript数据结构与算法第3版》: 斐波那契数列是另一个可以用递归解决的问题。它是一个由 0、 1、 1、 2、 3、 5、 8、 13、 21、 34 等数组成的序列。数 2 由 1 + 1 得到,数 3 由 1 + 2 得到,数 5 由 2 + 3 得到,以此类推。斐波 那契数列的定义如下。
- 位置 0 的斐波那契数是零。
- 1 和 2 的斐波那契数是 1。
- n(此处 n > 2)的斐波那契数是(n - 1)的斐波那契数加上(n - 2)的斐波那契数。
function fibonacciMemoization(n) {
const memo = [0, 1]; // {1}
const fibonacci = (n) => {
if (memo[n] != null){
console.log('memo!=null--index='+n, 'val='+memo[n])
return memo[n]; // {2}
}
memo[n] = fibonacci(n - 1) + fibonacci(n - 2); // {3}
console.log('memo index='+n, memo)
return memo[n]
};
return fibonacci;
}
let num= fibonacciMemoization(5)(5)
console.log('num', num)
在上面的代码中,我们声明了一个 memo 数组来缓存所有的计算结果(行{1})。如果结果已经被计算了,我们就返回它(行{2}),否则计算该结果并将它加入缓存(行{3})。
看下控制台的打印内容:
- memo!=null--index=1 val=1
- memo!=null--index=0 val=0
- memo index=2 (3) [0, 1, 1]
- memo!=null--index=1 val=1
- memo index=3 (4) [0, 1, 1, 2]
- memo!=null--index=2 val=1
- memo index=4 (5) [0, 1, 1, 2, 3]
- memo!=null--index=3 val=2
- memo index=5 (6) [0, 1, 1, 2, 3, 5]
- num 5
根据打印的内容,分析可得出计算的运行轨迹,看下图
递归是一种栈数据结构的实例应用,从一个节点出发后,只有最终触发了基线条件后,才会一层层从调用栈弹出结果,是一种后进先出的数据运行机制。像一颗倒置的树,从上到下,从左到右,然后从下而上的顺序遍历并计算出结果,只有计算完每一颗子树后,才会继续遍历右边的子树
由于位置4节点下的位置2和位置5节点下的位置3的斐波那契数已经在蓝色的箭头轨迹计算过,因此,下次计算时不会继续拆解并继续往下便遍历,直接返回结果1和2