动态规划经典问题
面试官问:"爬楼梯,一次可以爬1步或2步,爬到第n层有几种方法?"
候选人小张回答:"斐波那契数列,f(n) = f(n-1) + f(n-2)。"
面试官追问:"如果一次可以爬1步、2步或3步呢?"
小张说:"那就改成 f(n) = f(n-1) + f(n-2) + f(n-3)。"
面试官点点头,又问:"如果台阶有代价,爬每一步都要花钱,怎么求最小代价?"
小张彻底卡住了...
一、从一个问题开始
动态规划(DP)是面试中最难的算法之一,90%的候选人知道斐波那契,但能独立解决背包问题、编辑距离的不超过30%。
今天,我们把动态规划讲透。
【直观类比】
动态规划就像剥洋葱:
- 把大问题分解成小问题
- 小问题的解复用给大问题
- 从最小的子问题自底向上求解
二、动态规划基础
2.1 动态规划的三大条件
一个问题是动态规划问题,必须满足:
- 最优子结构:子问题的最优解能推出原问题的最优解
- 无后效性:当前状态的选择不影响后续状态
- 重叠子问题:子问题会被重复计算
2.2 动态规划的两种实现
三、经典问题
3.1 爬楼梯(Fibonacci变体)
3.2 最小花费爬楼梯
3.3 背包问题
3.4 编辑距离
四、DP问题解题套路
4.1 四步法
4.2 常见DP类型
五、面试高频追问
5.1 追问一:什么情况下需要二维DP?
当状态需要两个维度时:
5.2 追问二:空间优化怎么做?
如果当前状态只依赖前几个状态,就可以压缩空间:
5.3 追问三:DP和递归的区别?
六、常见误区
❌ 误区一:所有问题都能用DP
实际情况:DP只适用于有最优子结构和重叠子问题的问题。
❌ 误区二:DP一定要用二维数组
实际情况:很多问题可以优化到一维数组。
❌ 误区三:空间优化总是可行的
实际情况:有些问题必须用二维数组,因为依赖关系比较复杂。
七、记忆技巧
用口诀记住DP四步:
定义状态写方程,初始条件不能忘,遍历顺序要看清,空间优化看依赖
用一句话记住DP的本质:
DP就是用空间换时间,把重复计算变成查表
八、实战检验
检验一:力扣70题 - 爬楼梯
检验二:力扣416题 - 分割等和子集
九、总结
动态规划的核心是分解问题、复用子问题答案:
- 定义状态:搞清楚 dp[i] 表示什么
- 状态转移:dp[i] = f(dp[i-1], dp[i-2], ...)
- 初始化:边界条件
- 空间优化:看依赖关系
记住这三句话:
- DP的本质是把指数级的递归优化成多项式级的递推
- 空间优化要看状态依赖,能省就省
- DP难在定义状态,状态定义对了就成功一半
下一篇文章,我们来聊聊双指针技巧,看看如何用O(1)空间解决数组问题。