题目:
给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
注意:
每个数组中的元素不会超过 100
数组的大小不会超过 200
示例 1:
输入: [1, 5, 11, 5]
输出: true
解释: 数组可以分割成 [1, 5, 5] 和 [11].
示例 2:
输入: [1, 2, 3, 5]
输出: false
解释: 数组不能分割成两个元素和相等的子集.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/partition-equal-subset-sum
思路:
定义dp[i][j] ,表示 nums[0,i-1] 的子数组中,是否能组成和为 j 1、当 dp[i-1][j]为 true 时,dp[i][j] = true 2、当j == nums[i-1] 时,dp[i][j] = true 3、当j-nums[i-1]<0 时, dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i-1]]
Java代码如下:
public boolean canPartition1(int[] nums) {
int sum = Arrays.stream(nums).sum();
if(sum%2==1){
return false;
}
int target = sum/2;
if(target==0){
return true;
}
boolean[][] dp = new boolean[nums.length+1][target+1];
// 定义dp[i][j] ,表示 nums[0,i-1] 的子数组中,是否能组成和为 j
// 1、当 dp[i-1][j]为 true 时,dp[i][j] = true
// 2、当j == nums[i-1] 时,dp[i][j] = true
// 3、当j-nums[i-1]<0 时, dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i-1]]
for(int i=1;i<nums.length+1;i++){
for(int j=1;j<target+1;j++){
dp[i][j] = dp[i-1][j]; //当 dp[i-1][j]为 true 时,dp[i][j] = true
if(j == nums[i-1]){ // 当j == nums[i-1] 时,dp[i][j] = true
dp[i][j] = true;
}
if(j-nums[i-1]<0){
continue;
}
dp[i][j] = dp[i][j] || dp[i-1][j-nums[i-1]]; // 当j-nums[i-1]<0 时, dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i-1]]
}
}
return dp[nums.length][target];
}
c++
class Solution {
public:
bool canPartition(vector<int>& nums) {
int n = nums.size();
int sum = 0;
for(int num:nums) {
sum += num;
}
if(sum %2 ==1) {
return false;
}
int target = sum / 2;
// 定义二维数组 dp , dp[i][j] 表示前 i个元素中是否有元素的和为 j
vector<vector<bool>> dp(n+1,vector<bool>(target+1));
// 初始化
// 状态转移
for(int i=1;i<n+1;i++) {
for(int j=1;j<target+1;j++) {
if(nums[i-1] == j) {
dp[i][j] = true;
} else {
if(j-nums[i-1]>=0) {
dp[i][j] = dp[i-1][j] | dp[i-1][j-nums[i-1]];
} else {
dp[i][j] = dp[i-1][j];
}
}
}
}
return dp[n][target];
}
};