由易到难涉及的几个例题:
- LeetCode 198. House Robber 打家劫舍(Easy)
- LeetCode 1143. Longest Common Subsequence 最长公共子序列(Medium)
- LeetCode 72. Edit Distance 编辑距离(Hard)
最后两个为二维动态规划问题
动态规划的解题方法:
- 定义子问题:子问题是和原问题差不多的问题,但是并不完全一样,且规模较小。通常原问题可能是一个数组,在这个数组内需要进行某种有规律的运算,那定义到子问题可能就是将数组中的相邻几个元素或者将某一元素前面的所有元素拿出来作为一个新的元素,这个新元素可能是类似元组的一样的感觉,依次排列下去就又可以组成一个新的子问题数组。
- 写出子问题的递推关系:子问题的递推关系往往是反直觉的,因此在代码中很难直观的看出有什么逻辑。通常都是整理出一个公式,然后对dp数组中的所有子问题通过这个公式进行递归或者遍历子集。(重要,这一步也是很好的锻炼逻辑思维,帮助拒绝直觉性的思维)
- 确定 DP 数组的计算顺序:dp数组即子问题数组,计算方法包括自顶向下的递归和自底向上的循环方法。
- 空间优化(可选):类似于斐波那契数列的递推,每次只需要3个变量就可以了,这样节省了存所有子问题数组的空间,下一个子问题可以通过上一个子问题得出。
**
打家劫舍:
**
-
定义子问题:
-原问题:从全部房子中能偷到的最大金额,假设有n间房子
-子问题:从k间房子中能偷到的最大金额,且k<=n,结果为f(k),当k等于n时结果就是原问题想要的
-分析: 从一间房开始,当k每增加1,f(k+1)必然携带着f(k)有关的信息,不同的自变量带到同一个函数里肯定会有重合的部分,类似于自相关这样(瞎猜的) -
子问题的递推关系:
-寻找不同的自变量之间的关系:打家劫舍这个问题很明显,因为不能偷相邻的房子,所以偷前k间房子的时候1⃣️偷前k-1间房最后一间不偷2⃣️偷前k-2间房子加最后一间,然后再从这两种方案中选最大的那个。此时得出来的f(k)就能作为结果,去找f(k+1)的最大结果,规律就在这里诞生了。
-公式: f ( k ) = { f ( k − 2 ) + H K − 1 f ( k − 1 ) \\f(k) = \lbrace ^{\\f(k-1)} _{\\f(k-2)+H_{K-1}} f(k)={ f(k−2)+HK−1<