斐波那契数列

71 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情

斐波那契数列

斐波那契数,来源于意大利语Successione di Fibonacci,又称为菲波拿契数、菲波那西数、斐氏数、黄金分割数。所形成的数列就称为斐波那契数列,同样也可称为菲波拿契数列、菲波那西数列、斐氏数列和黄金分割数列

在数学上,斐波那契数列是以递归的形式来定义的:

F0 = 0
F1 = 1
F(n) = F(n-1) + F(n-2),其中n>=2

爬楼梯

描述

现在在你面前有个n阶的楼梯,你每次可以上1个或2各台阶,问:爬上楼梯总共有多少种走法?

其中n的范围是:

1 ≤ n ≤ 45

分析

如果按照我们上楼梯的顺序来考虑的话,那一步步推。

第一步肯定只有一种方式;

第二步就可能存在两种方式了:一次跨2步,或者说分两次,每次跨1步;

那第三步呢?

可以是从第一步跨2步上来,也可能是从第二步跨1步上,总的走法应该就是到达第一步走法加上到达第二步走法相加;

再往下推,到第四步,能到第四步的走法也只有两种,要么是从第二步跨2步,要么是从第三步跨1步,步数仍然是两者走法相加的总和。

其实我们从楼梯顶往下推,也能得出同样的规律总结:F(n) = F(n-1) + F(n-2)。这其实就是我们上面说的斐波那契数列的数学表达形式。

程序实现

var climbStairs = function(n) {
  return n <= 2 ? n : climbStairs(n-1) + climbStairs(n-2)
};

这是一个看着非常简单的写法,执行出来的结果也是对的。但有个很大的不足,就是执行时间很长,把n=45,一般都要10s左右,那明显不能用。

为什么这个写法这么耗时呢?

如果我们都一步步拆开来看,会发现:里面有大量的重复运算。F(5)会计算F(4)和F(3),而F(4)会计算F(3)和F(2),这样F(4)就相当于重复执行了。

我们要把执行过的数据缓存起来直接用于运算。

var climbStairs = function(n) {
  if (n <= 3) return n
  const memo = {
    1: 1,
    2: 2,
    3: 3
  }
  for (let i = 3; i <= n; i++) {
    memo[i] = memo[i-1] + memo[i-2]
  }
  return memo[n]
};