LeetCode-416-分割等和子集
参考
「代码随想录」帮你把0-1背包学个通透!
494. 目标和,动态规划之01背包问题
思路
题目要求把数组分割成2个等和的子集,相当于找到一个和为sum/2的子集,则target=sum/2
1. 如果sum为奇数,无法分割,返回false
2. dp[j]:表示是否存在和为j的子集
3. 初始化:最后是返回dp[target],因此长度为target+1,其中dp[0]=true,表示空集一定可以取到
4. 状态转移:
- 对于遍历到的nums[i],有两种选择,选或不选,有以下递推式
- dp[j]=dp[j]||dp[j-nums[i]]
- 只要有一个为true即可,因此使用or
- 这其实是一个01背包问题,因此内循环倒序遍历
代码
public boolean canPartition(int[] nums) {
int len=nums.length;
int sum=0;
for (int num:nums) {
sum+=num;
}
if(sum%2==1)return false;
int target=sum/2;
boolean []dp=new boolean[target+1];
dp[0]=true;
for(int i=0;i<nums.length;i++){
for(int j=target;j>=nums[i];j--){
dp[j]=dp[j]||dp[j-nums[i]];
}
}
return dp[target];
}
public boolean canPartition(int[] nums) {
int sum=0;
for(int i=0;i<nums.length;i++){
sum+=nums[i];
}
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]);
}
}
return dp[target]==target;
}