该题的思路其实可以转化为超市购物0-1背包问题,通过求所有数的和的1/2得到我们要找到的目标数,通过动态规划来求解
给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。
输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。
1 <= nums.length <= 200
1 <= nums[i] <= 100
class Solution {
public:
//思路一:用回溯法
/*
bool canPartition(vector& nums) {
int sum=0;
//计算和
for(int i=0;i& nums,int temp,int mark,int dp){
if(temp==mark){
return true;
}
if(temp>mark){
return false;
}
for(int i=dp+1;i
//思路二:传统的动态规划求解,也就是0-1背包问题
/*
dp[i][j] = dp[i-1][j] or dp[i-1][j-nums[i]]
*/
bool canPartition(vector<int>& nums) {
int n = nums.size();
if (n < 2) {
return false;
}
//计算总和,背包问题找到能否有一组数使得为sum/2
int sum = accumulate(nums.begin(), nums.end(), 0);
int maxNum = *max_element(nums.begin(), nums.end());
if (sum & 1) {
return false;
}
int target = sum / 2;
if (maxNum > target) {
return false;
}
vector<vector<int>> dp(n,vector<int>(target+1,0));
for (int i = 0; i < n; i++) {
dp[i][0] = true;
}
dp[0][nums[0]] = true;
for (int i=1;i<n;i++) {
int num=nums[i];
for (int j=1; j<=target;j++) {
if (j >= num) {
dp[i][j]=dp[i-1][j]|dp[i-1][j-num];
} else {
dp[i][j]=dp[i-1][j];
}
}
}
return dp[n-1][target];
}
};