给你一个 只包含正整数 的 非空 数组 nums
。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
思路:将数组分割成相等的两个子集,也就是说在数组中任意取如果能取到和为sum/2,则表示可以分。用01背包的概念等价:
1、dp数组的下标及其意义:dp[j]表示目标和为j时此时的和为dp[j];
2、递推关系式:和滚动数组类似,dp[j]=max(dp[j],dp[j-nums[i]]+nums[i]);
3、初始化:nums[i]均为大于0的数,所以都初始化为0即可;
4、遍历顺序:先物品,再背包,注意背包需要倒序,以及背包的停止条件;
5、举例推导dp数组。
class Solution {
public:
bool canPartition(vector<int>& nums) {
//dp[j]的含义:目标和为j此时的和
//初始化
vector<int> dp(20001,0);
//确定遍历顺序:先物品,再背包且背包倒序
int sum=accumulate(nums.begin(),nums.end(),0);
if(sum%2==1) return false;//不能分成元素和相等的子集
int target=sum/2;
for(int i=0;i<nums.size();i++)
{
for(int j=target;j>=nums[i];j--)
{
dp[j]=max(dp[j],dp[j-nums[i]]+nums[i]);
}
}
if(dp[target]==target) return true;
return false;
}
};