动态规划
线性dp
lc 377: 与完全背包的不同点在于:[1,3],[3,1]被算作两个不同的答案。因此解法类似permutation型的回溯。 如果用cache修饰 dfs, 则不能使用全局变量res来计算个数,必须把res作为 dfs的返回值。
LC 139: 单词拆分
leetcode可以通过leet和code组成。如果code在 wordSet中,那么dp[9]=dp[4]
House Robber
LC 198: 空间优化
LC 213 打家劫舍 II: 所有房子围成一圈。考虑只能偷前(n-1)个房子的情况,和只能偷后(n-1)个房子的情况
最大子数组和
LC 53:dp[i]存放以当前元素结尾的最大和
dp[i]=max(dp[i-1]+nums[i], nums[i])
空间优化:
|
|
LC 1749 任意子数组和的绝对值的最大值:
遍历过程中,保持一个以当前元素结尾的最大和与最小和。绝对值最大->子数组和最大或最小
网格图 DP
基础题只需要做:63. 不同路径 II
dp[i+1][j+1]表示遍历到grid[i][j]时的方案数。初始化时,只需要考虑dp[1]这一行的值
最长回文子串
dp[j][i]表示s[j:i+1]是否为回文。i从左往右遍历,j从i往左遍历。
01背包
lc 494
记忆化搜索:选恰好k个,使得容量恰好等于c,求方案数. 递推是从后往前,dp只不过是把递推改写成了从前往后遍历。
|
|
把这个翻译成 dp
|
|
lc 3180
给你一个整数数组 rewardValues,长度为 n,代表奖励的值。 最初,你的总奖励 x 为 0,所有下标都是 未标记 的。你可以执行以下操作 任意次 :
从区间 [0, n - 1] 中选择一个 未标记 的下标 i。 如果 rewardValues[i] 大于 你当前的总奖励 x,则将 rewardValues[i] 加到 x 上(即 x = x + rewardValues[i]),并 标记 下标 i。 以整数形式返回执行最优操作能够获得的 最大 总奖励。
dp[i][j]表示从前i个物品中,能否拿到和为j
完全背包
有 n个物品,第i个物品的体积为w[i], 价值为v[i],每个物体能选无限次,容量为 capacity,求最大价值。
dfs(i, c)=dfs(i-1, c)+dfs(i, c-w[i])
LC 322 coin change
零钱价值视为体积,每个的价值为1. amount视为capacity,求体积恰好为capacity的时候,最小价值。
|
|
|
|
最长公共子序列
LC 1143
dfs(i, j)表示遍历到s[i]和t[j]时,从前往后最长公共子序列的长度。
- 如果s[i]==t[j],必须选当前字符
dfs(i, j)=dfs(i-1, j-1)+1;
- 如果s[i]!=t[j]
dfs(i, j)=max(dfs(i, j-1), dfs(i-1, j))
LC 72 编辑距离
dfs(i, j)表示遍历到s[i]和t[j]时,为保持两个字符串相同,所需要的操作数
s: rorse, t: rose
此处遍历到这两个字符不同,如果对 S 执行删除操作,相当于
dfs(i, j)=dfs(i-1, j)+1
s: ct, t: cat
如果此时对S执行添加操作,相当于
dfs(0, 0)=0, dfs(0, 1)=dfs(0, 0)+1=1
dfs(i, j)=dfs(i, j-1)+1
类似地,对 S 执行替换操作,相当于
dfs(i, j)=dfs(i-1, j-1)+1
当遍历到s[i]和t[j]时, 如果他们不相同,则需要遍历三种情况,看看当前字母前面的字母是什么样子的。所以,
dfs(i, j)=min(dfs(i-1, j), dfs(i, j-1), dfs(i-1, j-1))+1
💡注意边界条件。dp[0][0]=0, dp[i][0]=i, dp[0][j]=j. 初始化为(m+1)*(n+1)的矩阵,dp[i][j]表示遍历到word1的第i个和word2的第j个,也就是word1[i+1], word2[j+1]
LC 3290 最高乘法得分
a = [3,2,5,6], b = [2,-6,4,-5,-3,2,-7] 从 b的最后一个元素开始思考。
如果选它,那么考虑[3,2,5]和[2,-6,…,2]中间元素相乘的最大值。
如果不选它,那么考虑[3,2,5,6]和[2,-6,…,2]中间元素相乘的最大值。
|
|
初始化dp[0]=[0]*(n+1),因为考虑到数组 a遍历到0(还没开始遍历的时候),不管b数组遍历到哪里,初始的乘积和为 0. 也可思考循环赋值过程,如最后一行的注释。
区间DP
状态转移方向:从中间到两边,i倒序遍历,j正序遍历
516. 最长回文子序列: 选/不选
|
|
注意递推的遍历顺序。
|
|
LC 5
dp[i][j]记录当前字符串是否为回文;
需要 start 变量记录字符串的开头
1039. 多边形三角剖分的最低得分
区间dp一定是从中间往两边蔓延。
|
|
dp如何初始化?看递归的尽头是什么。
比如这题考虑i,k,j=0,1,2时,dp[i][k]必须为0. 所以所有dp[i][i+1]=0
最长递增子序列
回溯->记忆化搜索->动态规划
贪心+二分可实现最优