文章目录
背包
01背包
416. 分割等和子集
//f[i][j]表示能否从 nums中前i个 选出一个和恰好等于 j 的子序列.这不就是01背包
f[i][j] = f[i-1][j - nums[i]] || f[i-1][j] 选和不选
01背包优化成一维形式,i维度不要,内层循环从target递减
也可以用记忆化搜索做
class Solution {
public boolean canPartition(int[] nums) {
//f[i][j]表示能否从 nums中前i个 选出一个和恰好等于 j 的子序列.这不就是01背包
//f[i][j] = f[i-1][j - nums[i]] || f[i-1][j] 选和不选
//01背包优化成一维形式,i维度不要,内层循环从target递减
int n = nums.length;
int target = 0;
for(int i = 0; i < n; i ++)
target += nums[i];
if(target % 2 != 0) return false;
target /= 2;
boolean[] f = new boolean [target+1];
f[0] = true;
for(int i = 1; i <= n; i ++) {
for(int j = target; j >= nums[i-1]; j --) {
f[j] = f[j - nums[i-1]] || f[j];
}
}
return f[target];
}
}
完全背包
外层是物品(数组)遍历,内层是限制(容量价值)遍历
279. 完全平方数
完全背包问题
class Solution {
public int numSquares(int n) {
int[] f = new int[n+1];
f[1] = 1;
for(int i = 1; i <= n; i ++) {
f[i] = i; // 最坏的情况就是每次+1
for(int j = 1 ;j <= n; j ++)
if(i >= j*j)
f[i] = Math.min(f[i], f[i - j*j] + 1);
}
return f[n];
}
}
322. 零钱兑换
也是完全背包问题
for(int i = 1; i <= n; i ++ ) {
for(int j = c[i-1]; j <= amount; j ++) {
dp[j] = Math.min(dp[j], dp[j-c[i-1]] + 1);
}
}
Arrays.fill(dp, amount + 1); //因为是最小值,初始化0会一直是0
class Solution {
public int coinChange(int[] c, int amount) {
//dp[i]:表示最小个数
//dp[j] = min(dp[j], dp[j-c[i]] + 1)
int n = c.length;
int[] dp = new int[amount + 1];
Arrays.fill(dp, amount + 1); //因为是最小值,初始化0会一直是0
dp[0] = 0;
for(int i = 1; i <= n; i ++ ) {
for(int j = c[i-1]; j <= amount; j ++) {
dp[j] = Math.min(dp[j], dp[j-c[i-1]] + 1);
}
}
int ans = dp[amount];
return ans < amount + 1 ? ans : -1;
}
}
两个字符串DP
LCR 095. 最长公共子序列
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
//设 f(i,j)表示第一个字符串的前 i个字符和第二个字符串的前 j个字符的最长公共子序列
//dp[i][j] = max(dp[i-1][j], dp[i][j-1],dp[i-1][j-1] + 1) 或者 max(dp[i-1][j], dp[i][j-1])
//忽略text1[i]或者忽略text2[j]
//这个是 求两个字符串的公共子序列,不需要len 不是遍历len对len分1 2 更长的情况的
int n = text1.length(), m = text2.length();
int[][] dp = new int [n+1][m+1];
int ans = 0;
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= m; j ++) {
if(Objects.equals(text1.charAt(i-1),text2.charAt(j-1)))
dp[i][j] = Math.max(Math.max(dp[i-1][j], dp[i][j-1]),dp[i-1][j-1] + 1);
else
dp[i][j] =