416. Partition Equal Subset Sum
Problem Description
Given an integer array nums, return true if you can partition the array into two subsets such that the sum of the elements in both subsets is equal or false otherwise.
Example 1:
Input: nums = [1,5,11,5]
Output: true
Explanation: The array can be partitioned as [1, 5, 5] and [11].
Example 2:
Input: nums = [1,2,3,5]
Output: false
Explanation: The array cannot be partitioned into equal sum subsets.
Constraints:
1 <= nums.length <= 2001 <= nums[i] <= 100
Solution
Python Solution
class Solution:
def canPartition(self, nums: List[int]) -> bool:
total_sum = sum(nums)
# If total sum is odd, we can't partition into equal subsets
if total_sum % 2 != 0:
return False
target = total_sum // 2
dp = set([0])
# For each number, check if we can make any new sums
for num in nums:
# We need to create a new set to avoid modifying while iterating
next_dp = dp.copy()
for curr_sum in dp:
next_sum = curr_sum + num
if next_sum == target:
return True
if next_sum < target:
next_dp.add(next_sum)
dp = next_dp
return False
Time Complexity: O(n * sum)
Where n is the length of nums and sum is the total sum of all numbers.
Space Complexity: O(sum)
For storing all possible sums in the dp set.
Java Solution
class Solution {
public boolean canPartition(int[] nums) {
int totalSum = 0;
for (int num : nums) {
totalSum += num;
}
// If total sum is odd, we can't partition into equal subsets
if (totalSum % 2 != 0) {
return false;
}
int target = totalSum / 2;
boolean[] dp = new boolean[target + 1];
dp[0] = true;
// For each number, check if we can make any new sums
for (int num : nums) {
for (int i = target; i >= num; i--) {
dp[i] = dp[i] || dp[i - num];
}
}
return dp[target];
}
}
Time Complexity: O(n * sum)
Where n is the length of nums and sum is the total sum of all numbers.
Space Complexity: O(sum)
For storing the dp array.
C++ Solution
class Solution {
public:
bool canPartition(vector& nums) {
int totalSum = accumulate(nums.begin(), nums.end(), 0);
// If total sum is odd, we can't partition into equal subsets
if (totalSum % 2 != 0) {
return false;
}
int target = totalSum / 2;
vector dp(target + 1, false);
dp[0] = true;
// For each number, check if we can make any new sums
for (int num : nums) {
for (int i = target; i >= num; i--) {
dp[i] = dp[i] || dp[i - num];
}
}
return dp[target];
}
};
Time Complexity: O(n * sum)
Where n is the length of nums and sum is the total sum of all numbers.
Space Complexity: O(sum)
For storing the dp vector.
JavaScript Solution
/**
* @param {number[]} nums
* @return {boolean}
*/
var canPartition = function(nums) {
const totalSum = nums.reduce((a, b) => a + b, 0);
// If total sum is odd, we can't partition into equal subsets
if (totalSum % 2 !== 0) {
return false;
}
const target = totalSum / 2;
const dp = new Set([0]);
// For each number, check if we can make any new sums
for (const num of nums) {
const nextDp = new Set(dp);
for (const currSum of dp) {
const nextSum = currSum + num;
if (nextSum === target) {
return true;
}
if (nextSum < target) {
nextDp.add(nextSum);
}
}
dp = nextDp;
}
return false;
};
Time Complexity: O(n * sum)
Where n is the length of nums and sum is the total sum of all numbers.
Space Complexity: O(sum)
For storing all possible sums in the dp set.
C# Solution
public class Solution {
public bool CanPartition(int[] nums) {
int totalSum = nums.Sum();
// If total sum is odd, we can't partition into equal subsets
if (totalSum % 2 != 0) {
return false;
}
int target = totalSum / 2;
bool[] dp = new bool[target + 1];
dp[0] = true;
// For each number, check if we can make any new sums
foreach (int num in nums) {
for (int i = target; i >= num; i--) {
dp[i] = dp[i] || dp[i - num];
}
}
return dp[target];
}
}
Time Complexity: O(n * sum)
Where n is the length of nums and sum is the total sum of all numbers.
Space Complexity: O(sum)
For storing the dp array.
Approach Explanation
The solution uses dynamic programming approach:
- Key Insights:
- Sum calculation
- Subset problem
- DP optimization
- State tracking
- Algorithm Steps:
- Check total sum
- Find target sum
- Build DP table
- Track possible sums
Implementation Details:
- Sum handling
- State management
- Memory optimization
- Early termination
Optimization Insights:
- Space reduction
- Early checks
- Efficient storage
- Quick validation
Edge Cases:
- Empty array
- Single element
- Odd total sum
- Large numbers