分割等和子集 LeetCode 416
题目链接:[LeetCode 416 - 中等]
思路
解决01背包问题:
①确定dp数组:为容量为target的背包中,装入物品的价值
②确定遍历顺序:由于使用的是一维数组,因此采用的是先遍历物品,后倒序遍历背包。
动态规划:
class Solution {
public boolean canPartition(int[] nums) {
int sum = 0;
for(int num:nums){
sum+=num;
}
if(sum%2==1)return false;
int target = sum/2;
int[] dp = new int[target+1];
for(int i=0;i<nums.length;i++){
for(int j=target;j>=nums[i];j--){
dp[j]=Math.max(dp[j],dp[j-nums[i]]+nums[i]);
}
if(dp[target]==target)return true;
}
return dp[target]==target;
}
}
最后一块石头的重量 II LeetCode 1049
题目链接:[LeetCode 1049 - 中等]
思路
解决01背包问题:
①将石头相撞问题转化为最后石头的最小重量:因此计算石头的重量,然后整体/2即为背包的大小
②dp数组的意义:背包大小为target的情况下,可以装下的石头的最大重量
③遍历方式:先遍历物品,然后后序遍历背包
⑤题解的答案:一堆石头的大小为dp[target],另一堆石头的大小为sum - dp[target],因此他们相撞之后得到的结果为:sum - 2*dp[target]
动态规划:
class Solution {
public int lastStoneWeightII(int[] stones) {
int sum=0;
for(int stone:stones){
sum+=stone;
}
int target=sum/2;
int[] dp = new int[target+1];
for(int i=0;i<stones.length;i++){
for(int j=target;j>=stones[i];j--){
dp[j]=Math.max(dp[j],dp[j-stones[i]]+stones[i]);
}
}
return sum - 2*dp[target];
}
}
目标和 LeetCode 494
题目链接:[LeetCode 494 - 中等]
思路
01背包问题:
①如何敲定背包大小:bagSize = (target+sum)/2;(很巧妙)
②确定dp数组:int[] dp = new int[bagSize+1];????
③初始化dp数组:dp[0]=1; -> sum+target=0,所以dp[0]=1
④确定遍历顺序:先遍历物品,后倒序遍历背包
动态规划:
class Solution {
public int findTargetSumWays(int[] nums, int target) {
int sum=0;
for(int num:nums){
sum+=num;
}
if(Math.abs(target)>sum)return 0;
if((target+sum)%2==1)return 0;
int bagSize = (target+sum)/2;
int[] dp = new int[bagSize+1];
dp[0]=1;
for(int i=0;i<nums.length;i++){
for(int j=bagSize;j>=nums[i];j--){
dp[j]+=dp[j-nums[i]];
}
}
return dp[bagSize];
}
}
一和零 LeetCode 474
题目链接:[LeetCode 474 - 中等]
思路
01背包问题: ①确定dp数组:二维数组,分别为0的个数和1的个数
②确定遍历顺序:先遍历0的个数,倒序遍历,再遍历1的个数,倒序遍历
③条件:dp[i][j]=Math.max(dp[i][j],dp[i-zeroNum][j-oneNum]+1);
动态规划:
class Solution {
public int findMaxForm(String[] strs, int m, int n) {
int[][] dp = new int[m+1][n+1];
int oneNum,zeroNum;
for(String str:strs){
oneNum=0;
zeroNum=0;
for(char ch:str.toCharArray()){
if(ch=='0'){
zeroNum++;
}else{
oneNum++;
}
}
for(int i=m;i>=zeroNum;i--){
for(int j=n;j>=oneNum;j--){
dp[i][j]=Math.max(dp[i][j],dp[i-zeroNum][j-oneNum]+1);
}
}
}
return dp[m][n];
}
}