给你一个 只包含正整数 的 非空 数组 nums
。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
思路:
可以认为是对数组中取部分元素,使得加合是所有元素之和的一半(转换成这个问题就会发现本题是标准的01背包问题,就是看每个元素是取还是不取就行)。
则dp[i][j]表示前i个元素,结果是j是否可能存在。dp[i][j]的构成是:
dp[i-1][j],视为第i个元素不取。
dp[i-1][j-num[i]],取第i个元素,但前提是dp[i-1][j-num[i]]得下标合法且存在。
dp[i][j]=dp[i-1][j](一定有) ||dp[i-1][j-num[i]](可能有)。
初始化:
对于i=0时,仅当j=0为真,其余情况均不可能达到。
对于j=0时,对任意i为真,因为一个都不取一定满足总和是j。
class Solution {
public:
bool canPartition(vector<int>& nums) {
int n=nums.size();
int k=0;
nums.insert(nums.begin(),0);
for(auto e:nums)
{
k+=e;
}
if(k%2!=0)
return false;
k/=2;
vector<vector<bool>>dp(n+1,vector<bool>(k+1,false));
for(int i=0;i<=n;i++)
{
dp[i][0]=true;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=k;j++)
{
dp[i][j]=dp[i-1][j];
if(j>=nums[i]&&dp[i-1][j-nums[i]])
dp[i][j]=dp[i-1][j]||dp[i-1][j-nums[i]];
}
}
return dp[n][k];
}
};