LeetCode探索(一):70_爬楼梯

1,055 阅读2分钟

这是我参与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数组,定义变量pq,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)。