图解题库 / 动态规划

70. 爬楼梯

简单 含交互动画

学完这道你应该能: 说清它为什么用「动态规划」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

题目描述

每次能爬 12 阶,爬到第 n 阶共有几种不同方法?

n = 5
输出 = 8

思路解析

直接写 f(n)=f(n-1)+f(n-2) 的递归,会把同一个 f(3)、f(2) 算很多遍,n 一大就极慢。咱改成「填表」,每个值只算一次。

想到第 i 阶,最后一步要么从 i-1 阶跨 1 阶上来,要么从 i-2 阶跨 2 阶上来。所以方法数 = 这两者之和。这就是「状态转移」。

建表:dp[i] 表示「到第 i 阶有几种走法」。咱要把这一行从左到右填满。

边界 · 第 1 阶:到第 1 阶只有 1 种走法(跨 1 阶)。dp[1] = 1。

边界 · 第 2 阶:到第 2 阶有 2 种:1+1,或者直接跨 2。dp[2] = 2。这两个是「地基」,不用算。

第 3 阶:到第 3 阶 = 到第 2 阶(2 种) + 到第 1 阶(1 种) = 3。把前两格相加填进来。

第 4 阶:同样规则:dp[4] = dp[3] + dp[2] = 3 + 2 = 5

第 5 阶:dp[5] = dp[4] + dp[3] = 5 + 3 = 8

答案:表格最后一格 dp[5] = 8 就是答案。每个值只算了一次。

1、2、3、5、8——每个数都是前两个之和。这就是斐波那契,DP 的最佳入门例子。

找到「当前格和前面格的关系」,再从地基填到目标——这就是 DP。打家劫舍、泰波那契都是同一套。

参考代码(Python)

Python
1def climbStairs(self, n):
2    if n == 1: return 1
3    if n == 2: return 2
4    memo = [0] * (n + 1)
5    memo[1] = 1                     # 地基
6    memo[2] = 2                     # 地基
7    for i in range(3, n + 1):
8        memo[i] = memo[i-1] + memo[i-2]  # 状态转移
9    return memo[n]

复杂度分析

  • 时间复杂度:O(n) —— 填 n 个格子
  • 空间复杂度:O(n) —— 一张表;其实可压成两个变量

套路模板

所有 DP 都是这四步:定义、递推、base、遍历顺序。当填空题做。

Python
1# 1.定义 dp[i] 含义  2.写递推  3.定 base  4.定遍历顺序
2dp = [0]*(n+1)
3dp[1], dp[2] = 1, 2          # base case
4for i in range(3, n+1):
5    dp[i] = dp[i-1] + dp[i-2]   # 递推
6return dp[n]

易错点

  • n=1/n=2 不特判 → ✅ 先处理 n<=2 的边界(否则 dp[2] 在 n=1 时越界)
  • 遍历方向写反 → ✅ 从小到大填(后面依赖前面)(算 dp[i] 时 dp[i-1] 必须已有值)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →3. 无重复字符的最长子串 ← 返回题库