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.
既然要找到兩個子集合的和相等,所以所有數字的總合不能是奇數。
dp[i][j]代表nums array裡index = 0到index = i - 1的數字中能否組成和為j的子集合。
// Bottom-Up Dynamic programming with 1D DP array
bool canPartition(vector<int>& nums) { // time: O(n * sum); space: O(sum)
int sum = accumulate(nums.begin(), nums.end(), 0);
if (sum & 1) return false;
int target = sum >> 1, n = nums.size();
// dp[i]: whether numbers in nums array can for a subset with sum of i
vector<bool> dp(target + 1, false);
dp[0] = true;
for (int i = 0; i < n; ++i) {
for (int j = target; j >= nums[i]; --j) {
dp[j] = dp[j] || dp[j - nums[i]];
}
}
return dp.back();
}
Recursion DFS在這比bottom-up DP有效率。
// DFS
bool helper(vector<int>& nums, int sum, int index) {
if (index < 0 || sum < nums[index]) return false;
if (sum == nums[index]) return true;
return helper(nums, sum - nums[index], index - 1) || helper(nums, sum, index - 1);
}
bool canPartition(vector<int>& nums) { // time: O(2^n); space: O(n)
int sum = accumulate(nums.begin(), nums.end(), 0);
if (sum & 1) return false;
return helper(nums, sum >> 1, nums.size() - 1);
}