【刷穿leetcode】70. 爬楼梯|刷题打卡

418 阅读3分钟

一、题目描述:

leetcode70题:爬楼梯

假设你正在爬楼梯。需要 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 阶

二、思路分析:

解法1:动态规划

假设n = 3,需要爬3级到楼顶。由题意可知,可以爬1个或是2个台阶,总共3种走法,这刚好是n=2走法加上n=1走法:
n=2有2种:

  • 1 阶 + 1 阶
  • 2 阶 n=1有1种:
  • 1 阶 通过归纳总结推导出动态规划的DP方程:f(n) = f(n-1) + f(n-2)
    下面我们来讨论边界条件。我们是从第 0 级开始爬的,所以从第 0 级爬到第 0 级我们可以看作只有一种方案,即 f(0) = 1;从第 0 级到第 1 级也只有一种方案,即爬一级,f(1) = 1。这两个作为边界条件就可以继续向后推导出第 n 级的正确结果。我们不妨写几项来验证一下,根据转移方程得到 f(2) = 2,f(3) = 3,f(4) = 5,……,我们把这些情况都枚举出来,发现计算的结果是正确的。

复杂度分析:

  • 时间复杂度:O(n),循环执行 n 次,因此时间复杂度为O(n)。
  • 空间复杂度:O(1),计算第n级的走法,只需记录n-1和n-2两个数的空间,空间复杂度是线性的,所以为O(1)。

解法2:公式

n较小时,使用上述动态规划效率很不错,但n变大时,就需要考虑减小时间复杂度,需要更好的解决方案。 n代入具体的数值进行如下推导:
输入 1: 输出 1
输入 2: 输出 2
输入 3: 输出 3
输入 4: 输出 5
输入 5: 输出 8
......
咦,目前相当满足斐波那契数列!!!
查一查它的通项公式:

复杂度分析:

  • 时间复杂度:O(logn),这里需要考虑Math.pow方法的影响。
  • 空间复杂度:O(1),没有产生额外空间开销。

三、AC 代码:

动态规划的代码

var climbStairs = function(n) {
  let dp = [];
  dp[0] = 1;
  dp[1] = 1;
  for(let i = 2;i <= n;i++) {
    dp[i] = dp[i-1] + dp[i-2];
  }
  return dp[n];
};

公式法的代码

// 公用常量
const sqrt5 = Math.sqrt(5);
var climbStairs = function(n) {
    // 斐波那契数列
    return (Math.pow((1 + sqrt5) / 2, n + 1) - Math.pow((1 - sqrt5) / 2, n + 1))/sqrt5
};

四、总结:

爬楼梯是leetcode经典动态规划题目,上述2种解法,我们主要是需要学习掌握动态规划。我们用动态规划来解题时,关键是推导出DP方程和确定DP边界状态。公式法是扩展学习斐波那契数列,是进阶解法,能够将时间复杂度降为O(logn)。

本文正在参与「掘金 3 月闯关活动」,点击查看活动详情