携手创作,共同成长!这是我参与「掘金日新计划 · 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]
};