跳转至

70. 爬楼梯(Climbing Stairs)

频次 ★★★★★ · 难度 🟢 · 高频:全厂

题目

每次可以爬 1 或 2 阶,到楼顶 n 阶有多少种不同方法。

示例:

输入: n = 3
输出: 3  (1+1+1, 1+2, 2+1)

思路

DP 入门:到达第 i 阶 = 从 i-1 迈 1 步 + 从 i-2 迈 2 步。dp[i] = dp[i-1] + dp[i-2],实际上就是斐波那契数列。

空间可优化:只用两个变量滚动。

代码

public int climbStairs(int n) {
    if (n <= 2) return n;
    int a = 1, b = 2;       // dp[1], dp[2]
    for (int i = 3; i <= n; i++) {
        int c = a + b;
        a = b;
        b = c;
    }
    return b;
}

dp 下标坐标系:独立 Choosing 与全书公约(70 = 雷区第一教训)

两个主流流派都对但坐标轴不同(70 实测双版互验全绿):

流派 A(dp[i]=到第 i+1 阶) 流派 B(dp[i]=到第 i 阶,下标=阶数)
数组长度 n n+1
地基 dp[0]=1, dp[1]=2 dp[0]=1(空走), dp[1]=1, dp[2]=2
循环 2..n-1 3..n
返回 dp[n-1] dp[n]

全书建议锁流派 B(让 dp 下标与题面量同名):多花一个 dp[0] 格子+一条"空走法=1 种"地基,换来 n/n-1/n+1 换算的零思维税——62/63/198/300/121 全书统一。

坐标系自查三问(写 DP 前自问): 1. dp[i] 语义中 i 最大到几 → 数组长度 = 那个数 + 1 2. 最后一个要填的下标 → 循环上限 3. 答案住哪个格子 → return 下标 = ①的语义终点(不是 n 也不是 n-1,除非恰好)

另:dp[0] 的值为 1 还是 0 没有对错、只有流派内自洽——语义"从 0 出发站 0 阶"=1 种空走法 vs "走 0 步不够格"=0。先定语义再定地基,别改测(用例会抓)。

复杂度

  • 时间:O(n)
  • 空间:O(1)

边界条件

  • n = 1:1 种
  • n = 2:2 种(1+1, 2)

变式

易错点

  • 第 n 阶是下标 n 不是 n-1——通常 dp[0] 表示地面(0 阶),dp[1]=1、dp[2]=2
  • 斐波那契数列不要写成递归(指数爆炸),用迭代或矩阵快速幂

面试追问

  • 如果一次能爬 1~k 阶? 广义斐波那契:dp[i] = sum(dp[i-1] + ... + dp[i-k]),注意 dp[0]=1

关联题