LCR 101. 分割等和子集
给定一个非空的正整数数组 nums ,请判断能否将这些数字分成元素和相等的两部分。
示例 1:
输入:nums = [1,5,11,5]
输出:true
解释:nums 可以分割成 [1, 5, 5] 和 [11] 。
示例 2:
输入:nums = [1,2,3,5]
输出:false
解释:nums 不可以分为和相等的两部分
提示:
1 <= nums.length <= 200
1 <= nums[i] <= 100
动态规划01背包
dp[i][j]表示从前 i 个数字中选出若干个,刚好可以使得被选出的数字其和为 j。
本题就是要返回dp[n-1][target]
class Solution {
public:
bool dp[205][10005];
bool canPartition(vector<int>& nums)
{
dp[0][0]=1;
int n=nums.size();
int sum=0;
for(int i=0;i<n;i++) sum+=nums[i];
if(sum%2!=0) return 0;
int target=sum/2;
for(int i=1;i<=target;i++) dp[0][i]=0;
for(int i=1;i<n;i++)
{
for(int j=0;j<=target;j++)
{
if(nums[i]>j) dp[i][j]=dp[i-1][j];
else dp[i][j]=dp[i-1][j]|dp[i-1][j-nums[i]];
}
}
return dp[n-1][target];
}
};
优化
class Solution {
public:
bool dp[10005];
bool canPartition(vector<int>& nums)
{
dp[0]=1;
int n=nums.size();
int sum=0;
for(int i=0;i<n;i++) sum+=nums[i];
if(sum%2!=0) return false;
int target=sum/2;
for(int i=1;i<n;i++)
{
for(int j=target;j>=nums[i];j--)
{
if(dp[target]) return true;
dp[j]=dp[j]|dp[j-nums[i]];
}
}
return dp[target];
}
};