记忆化递归求第N个位置的斐波那契数

390 阅读2分钟

《学习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 = [01]; // {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

根据打印的内容,分析可得出计算的运行轨迹,看下图

微信截图_20211210162043.png

递归是一种栈数据结构的实例应用,从一个节点出发后,只有最终触发了基线条件后,才会一层层从调用栈弹出结果,是一种后进先出的数据运行机制。像一颗倒置的树,从上到下,从左到右,然后从下而上的顺序遍历并计算出结果,只有计算完每一颗子树后,才会继续遍历右边的子树

由于位置4节点下的位置2和位置5节点下的位置3的斐波那契数已经在蓝色的箭头轨迹计算过,因此,下次计算时不会继续拆解并继续往下便遍历,直接返回结果1和2