前言
我们在刷题时会遇到很多种关于动态规划的问题,同时这也是很多企业面试时喜欢考察的一个点。为了更好的掌握动态规划问题,为此我开始着手学习动态规划的相关问题。并且在此系列纪录学习动态规划的成果。
学习全部基于知乎大佬的总结,此篇文章只是总结摘录:
爆肝整理220页《动态规划修炼之道:从入门到实战》来啦(附pdf下载),堪称最强!
什么是动态规划?
动态规划,英文名 Dynamic Programming,简称 DP。用作者直白的话讲就是:
将一个大的复杂的问题,拆成一个个的子问题,子问题再拆成更小的子问题,直至拆到到子问题可以用 确定的条件解答,之后通过这些子问题的解反向得到原问题的解。
动态规划可以解决什么问题?
可以由动态规划解决的问题应该有 4 个特点:
- 求最优性质问题
- 有重叠子问题
- 最优子结构
- 无后效性
由于只针对于刷题而言,这些特点可以不做了解。
动态规划解题步骤
主要就是 5 步,即:
- 确定 dp 状态
- 确定状态转移方程
- 确定初始化状态
- 确定状态转移顺序
- 确定最终解
1. 确定 dp 状态
这个其实就是确定 dp 数组代表的含义。比如 dp[i] 代表的是第 i 个 xxx 是 dp[i]。
2.确定状态转移方程
状态转移方程是 dp 的重点,好不夸张的说,写出了状态转移方程,我们基本成功了一大半。 那啥是状态转移方程呢?其实就是“递推公式”,“递推公式”相当于就是“递归 + 记忆化”。
而这个“记忆化”就是让我们“记住计算过的数值,减少重复计算”,意思就是“计算过的数就会记下来,存 在一个地方,再碰到的时候直接拿出来用,不要再计算了”。
这是动态规划的核心思想,通过这个来显著的降低代码的时间复杂度,提高执行效率。
同样,有利就有弊,因为记忆化会把“计算过的数会记下来”,这就额外开辟了内存空间来存储,增加了 空间复杂度。动态规划相当于拿了空间换时间。
3.确定初始化状态
这步就是确定 dp 数组的初始化情况,也就是可以确定的最小子问题的 dp 值。
4.确定状态转移顺序
这步就是确定 dp 数组的转移顺序,比如对于当前状态的 dp[i],是如何利用之前的计算值凑出它的最优 解来的。
5.确定最优解
这步就是最后确定的 return 值。