这是我参与11月更文挑战的第 8 天,活动详情查看:2021最后一次更文挑战
题目
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
思考
这也就是《剑指Offer》中的10 跳台阶。因为一次可以爬 1 或 2 个台阶,
假设有2个台阶,那么就有两种方法:1+1阶或者2阶;
假设有3个台阶,如示例2中所示,有3种方法;
假设有n个台阶,跳法的数量定义为f(n),
如果第一次跳了1阶,剩下的是n-1个台阶,跳法定义为f(n-1)。
如果第一次跳了2阶,剩下的是n-2个台阶,跳法定义为f(n-2)。
那么,我们可以得到:
f(n) = f(n-1) + f(n-2)
最终,我们可以得到:
| 1, n=1
f(n) = | 2, n=2
| f(n-1)+f(n-2), n>2且n为整数
这就是一个斐波那契数列,每一项可由前两项相加得到。
那么代码就不难写出来了。
解答
这里定义数组memo存储斐波那契数列的每一项,对于台阶数n,最终结果是memo[n]。代码如下:
/**
* @param {number} n
* @return {number}
*/
var climbStairs = function(n) {
let memo = [];
memo[0]=1;
memo[1]=1;
for(let i=2; i<=n; i++){
memo[i] = memo[i-1] + memo[i-2];
}
return memo[n];
};
复杂度分析
- 时间复杂度:for 循环执行了 n 次,时间复杂度为 O(n)。
- 空间复杂度:这里定义了数组memo存储计算结果,故空间复杂度为 O(n)。
优化
这里可以省去memo数组,定义变量p和q,for 循环中不断更新这两个值,并计算结果。
var climbStairs = function(n) {
let p = 0, q = 0, r = 1;
for (let i = 1; i <= n; ++i) {
p = q;
q = r;
r = p + q;
}
return r;
};
复杂度分析
- 时间复杂度:for 循环执行了 n 次,时间复杂度为 O(n)。
- 空间复杂度:这里只用了常数个变量作为辅助空间,空间复杂度为 O(1)。