Partition Equal Subset Sum
You're given an array nums of positive integers. Decide whether you can split it into two groups with equal sums, where every element goes into exactly one group and the groups don't need to be contiguous. Return true if such a split exists and false otherwise.
Examples
nums = [1,5,11,5] returns true
The total is 22, so each group needs 11. [1,5,5] and [11] both sum to 11.
nums = [1,2,3,5] returns false
The total is 11, which is odd, so it can't be split into two equal whole-number halves.
nums = [1,2,5] returns false
The total, 8, is even, so each group would need 4. No combination of 1, 2 and 5 adds up to 4, so the split is impossible.
Constraints
- 1 <= nums.length <= 200
- 1 <= nums[i] <= 100
Hints
If the total sum is odd you can stop early: otherwise, what's the smaller question that's equivalent?
0/1 knapsack: can any subset sum to total / 2?
If total is odd, return false; else target = total / 2. Build a boolean dp of size target + 1 with dp[0] = true. For each num, iterate j from target down to num and set dp[j] |= dp[j - num]. Return dp[target].
Drill This: Your Approach First
Approach
If the total is odd, return false. Otherwise ask whether some subset sums to target = total / 2, since the rest then sums to target too. Keep a boolean array dp where dp[s] is true if some subset of the numbers seen so far sums to s, starting with dp[0] = true. For each number n, sweep s from target down to n and set dp[s] = dp[s] or dp[s - n]; sweeping downward uses each number at most once. O(n * target) time, O(target) space.
Time
O(n * target)
Space
O(target)
Pitfall
Solutions
class Solution {
public boolean canPartition(int[] nums) {
int sum = 0;
for (int n : nums) sum += n;
if (sum % 2 != 0) return false;
int target = sum / 2;
boolean[] dp = new boolean[target + 1];
dp[0] = true;
for (int n : nums) {
for (int s = target; s >= n; s--) {
dp[s] = dp[s] || dp[s - n];
}
}
return dp[target];
}
}class Solution:
def canPartition(self, nums) -> bool:
total = sum(nums)
if total % 2:
return False
target = total // 2
dp = [False] * (target + 1)
dp[0] = True
for n in nums:
for s in range(target, n - 1, -1):
dp[s] = dp[s] or dp[s - n]
return dp[target]