70. 爬楼梯

简单 含交互动画

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

AI 私教 · 就着本题动画讲
卡住了不用硬扛,按 8 步把这题真正走通。
从读题、试解、找法到手写代码,边问边打勾,适合第一次系统学算法的同学。

题目描述

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

n = 5
输出 = 8

思路解析

最直接的想法是递归 f(n)=f(n-1)+f(n-2)。但 f(5) 要 f(4) 和 f(3),f(4) 又要 f(3) 和 f(2)……同一个 f(3)、f(2) 会被算很多遍,n 一大调用数指数膨胀。慢就慢在重复子问题

想到第 i 阶,最后一步要么从 i-1 阶跨 1 阶上来,要么从 i-2 阶跨 2 阶上来,所以 dp[i] = dp[i-1] + dp[i-2]。为什么能记表?每个 dp[i] 只算一次存进表,后面直接查,把递归里重复算的子问题省成一次——这就是「状态转移」加「记表」。

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

地基 · dp[0]:第 0 阶就是起点,「待在原地不动」算 1 种走法,dp[0] = 1。这是不依赖别人的地基。

地基 · dp[1]:到第 1 阶只有 1 种走法(跨 1 阶),dp[1] = 1。dp[0]、dp[1] 是两块「地基」,直接给定,不用算。

dp[2]:从这一格起,每个值都等于前两格之和:dp[2] = dp[1] + dp[0] = 1 + 1 = 2。两块依赖格(dep)亮起来。

dp[3]:依赖格往右滑一格:dp[3] = dp[2] + dp[1] = 2 + 1 = 3。注意 f(3) 在递归里要算好几遍,这里只算这一次。

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

dp[5]:dp[5] = dp[4] + dp[3] = 5 + 3 = 8。最后一格填好了。

答案 = 最后一格:表格最后一格 dp[5] = 8 就是答案。整行 1、1、2、3、5、8 每个值都只算了一次。

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

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

参考代码(Python)

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

复杂度分析

  • 时间复杂度:O(n) —— 只从 2 到 n 填一遍表,每格算一次
  • 空间复杂度:O(n) —— 一张长 n+1 的表;只依赖前两项,可压成两个变量降到 O(1)

套路模板

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

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

易错点

  • 错误写法:base 写成 dp[1]=1、dp[2]=2 但不开够空间正确写法:初值 dp[0]=1、dp[1]=1,遍历从 2 开始(base 选错或下标对不上,整行会整体错位,答案全错)
  • 错误写法:遍历方向写反(从大到小)正确写法:从小到大填,后面依赖前面(算 dp[i] 时 dp[i-1]、dp[i-2] 必须已经有值)
  • 错误写法:n 很小时 dp[1] 越界正确写法:先保证表长 n+1、按需特判 n<=1(否则 n=0/1 时访问不存在的格子)

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

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