LeetCode 70. 爬楼梯(Climbing Stairs)

难度:Easy ·

题目地址:https://leetcode.cn/problems/climbing-stairs/

标签:动态规划、滚动数组、斐波那契数列、数学 ·

进阶要求:能否使用仅 O(1) 空间复杂度实现解法


📝 题目描述

假设你正在爬楼梯。需要爬 n 阶才能到达楼顶。每次你只能爬 1 阶 或者 2 阶。请问有多少种不同的爬楼方法?

约束1 <= n <= 45

示例

示例 输入 输出 解释
1 n = 2 2 ① 1 阶 + 1 阶 ② 直接 2 阶
2 n = 3 3 ① 1+1+1 ② 1+2 ③ 2+1
3 n = 4 5 ---

💡 解题总览

本题本质为斐波那契数列变形,提供三种梯度解法:

  1. 解法一:暴力递归(入门直观,存在大量重复计算)
  2. 解法二:DP 数组动态规划(空间可优化,易懂)
  3. 解法三:滚动数组空间优化(最优解,O(1) 空间)

🔧 解法一:暴力递归(入门版)

🧠 解题思路

递推关系:要走到第 n 阶,最后一步只有两种选择:

  • 1 阶 :前面需要走完 n-1
  • 2 阶 :前面需要走完 n-2

公式f(n) = f(n-1) + f(n-2)

递归终止条件:

  • n = 1:只有 1 种走法
  • n = 2:只有 2 种走法

💻 完整代码(JavaScript)

javascript 复制代码
var climbStairs = function(n) {
    // 递归边界
    if (n === 1) return 1;
    if (n === 2) return 2;
    // 递推公式
    return climbStairs(n - 1) + climbStairs(n - 2);
};

⏱ 复杂度分析

  • 时间复杂度:O(2ⁿ) ------ 大量重复递归计算,数值稍大就超时
  • 空间复杂度:O(n) ------ 递归调用栈深度为 n

✅ 优缺点总结

优点 缺点
逻辑最简单,一眼看懂递推关系,适合理解基础思路 效率极低,n > 35 后运行极慢,无法通过大数据测试用例

🔧 解法二:DP 数组动态规划(标准 DP)

🧠 解题思路

  1. 用数组 dp 存储每一层台阶的方案数,避免递归重复计算
  2. dp[i] 代表爬到第 i 阶楼梯的总走法
  3. 状态转移方程:dp[i] = dp[i-1] + dp[i-2]
  4. 初始化边界:dp[1] = 1dp[2] = 2

💻 完整代码(JavaScript)

javascript 复制代码
var climbStairs = function(n) {
    if (n <= 2) return n;
    const dp = new Array(n + 1);
    dp[1] = 1;
    dp[2] = 2;
    for (let i = 3; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    return dp[n];
};

⏱ 复杂度分析

  • 时间复杂度:O(n) ------ 仅一次循环遍历
  • 空间复杂度:O(n) ------ 开辟了长度为 n 的 dp 数组

✅ 优缺点总结

优点 缺点
无重复计算,效率稳定;DP 思想标准模板,便于拓展同类 DP 题 额外占用数组存储空间,没有达到进阶 O(1) 空间要求

🏆 解法三:滚动数组(位序迭代最优解)

🧠 解题思路

观察 DP 数组,计算 dp[i] 只需要 dp[i-1]dp[i-2] 两个前值,不需要保存完整数组:

  • p :保存 dp[i-2](前两阶方案数)
  • q :保存 dp[i-1](前一阶方案数)
  • r :保存当前阶 dp[i] 的结果

每次循环滚动更新三个变量,全程不使用数组,空间压缩到常数级

💻 完整代码(JavaScript)

javascript 复制代码
var climbStairs = function(n) {
    // p = f(i-2), q = f(i-1), r = f(i)
    let p = 0, q = 0, r = 1;
    for (let i = 1; i <= n; ++i) {
        p = q;
        q = r;
        r = p + q;
    }
    return r;
};

⏱ 复杂度分析

  • 时间复杂度:O(n) ------ 单层循环遍历
  • 空间复杂度:O(1) ------ 仅固定 3 个变量,满足题目进阶要求

✨ 特点优势

  1. 时空双优,是本题最优官方推荐解法
  2. 代码极简,内存占用极小,大数据量性能稳定
  3. 滚动数组思想是动态规划空间优化的通用模板,可复用在各类 DP 题目中

📊 三种解法全面对比

解法 时间复杂度 空间复杂度 适用场景
暴力递归 O(2ⁿ) O(n) 仅理解思路,无法提交大数据
DP 数组 O(n) O(n) 学习 DP 基础,逻辑直观
滚动数组 O(n) O(1) 最优解,工程提交首选

⚠️ 核心易错点 & 核心知识点总结

🧩 核心知识点

  1. 斐波那契数列变形:爬楼梯是最经典的斐波那契应用题
  2. 动态规划滚动数组优化:DP 仅依赖前两项时,可抛弃数组只用变量迭代
  3. 递推思维:求解第 n 项结果,拆解为子问题 n-1、n-2 合并求解

🔥 高频易错点

易错点 说明
递归无记忆化 直接暴力递归会大量重复计算,直接超时
数组下标错位 dp 数组初始化时容易混淆台阶下标,出现结果偏差
滚动变量更新顺序 必须先更新 p → q → r,颠倒顺序会覆盖原值,计算错误
边界条件漏判 n=1n=2 不做特判会出现初始变量计算异常