416. Partition Equal Subset Sum
- Total Accepted: 5652
- Total Submissions: 15309
- Difficulty: Medium
- Contributors: Admin
Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.
Note:
- Each of the array element will not exceed 100.
- The array size will not exceed 200.
Example 1:
Input: [1, 5, 11, 5] Output: true Explanation: The array can be partitioned as [1, 5, 5] and [11].
Example 2:
Input: [1, 2, 3, 5] Output: false Explanation: The array cannot be partitioned into equal sum subsets.
解题思路:
本题问是否可以将一个集合分为两个子集使得两个子集和相等。这个问题可以等价为可否在一个集合中找到一个子集A,使得该子集A中所有元素的和为整个集合元素的和的一半。
对于集合的每个元素,或者属于子集A,或者不属于。由此可得到,即穷举所有元素的所有情况,看是否符合条件。
help(nums,half-nums[i],i-1)||help(nums,half,i-1)
但是直接这样显然会引起大量的重复运算导致超时。所以此处设立一个大小为half+1的res向量来保存中间的计算结果,初始化向量中所有项为-1。令i<=half,如果i可以表示为集合中的某些元素之和,则res[i]=1,否则res[i]=0,如果res[i]=-1,则说明i不知道是否能表示成集合中某些元素和,此时需要计算。
代码展示:
class Solution {
public:
vector<int> res;
bool help(vector<int> &nums,long long half,int i)
{
if(half<0) return false; // 一定要注意half小于0的情况,由于所有的元素均为正值,half小于0时必为false
if(res[half]!=-1) return res[half];
if(half==0)
{
res[0]=1;;
return true;
}
if(i<0)
{
res[half]=0;
return false;
}
res[half]=help(nums,half-nums[i],i-1)||help(nums,half,i-1);
if(res[half]==0) return false;
return true;
}
bool canPartition(vector<int>& nums) {
int n = nums.size();
if(!n) return true;
if(n==1&&(nums[0]!=0)) return false;
if(n==1&&(nums[0]==0)) return true;
long long sum=0;
for(int i=0;i<n;i++)
{
sum+=nums[i];
}
if(sum%2!=0) return false;
long long half = sum/2;
for(int i=0;i<=half;i++)
{
res.push_back(-1);
}
long long tmp_sum=0;
return help(nums,half,n-1);
}
};