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.
For example:
Input: nums = [1,5,11,5]
Output: true
Explanation: The array can be partitioned as [1, 5, 5]
and [11]
.
Input: nums = [1,2,3,5]
Output: false
Explanation: The array cannot be partitioned into equal sum subsets.
Constraints:
1 <= nums.length <= 200
1 <= nums[i] <= 100
Write a function to solve this problem efficiently.
## Partition Equal Subset Sum
This problem asks whether we can divide an array `nums` into two subsets such that the sum of elements in both subsets is equal. Let's explore different approaches to solve this problem, starting with a naive solution and then moving towards an optimal dynamic programming solution.
### 1. Naive Approach (Brute Force)
The most straightforward approach is to generate all possible subsets of `nums` and check if any two subsets have equal sums. This can be done using recursion.
```python
def canPartition_bruteforce(nums):
n = len(nums)
def subset_sum(index, current_sum, target_sum):
if current_sum == target_sum:
return True
if index >= n or current_sum > target_sum:
return False
# Include the current element or exclude it
return subset_sum(index + 1, current_sum + nums[index], target_sum) or \
subset_sum(index + 1, current_sum, target_sum)
total_sum = sum(nums)
if total_sum % 2 != 0:
return False # If the total sum is odd, it can't be partitioned into two equal subsets.
target_sum = total_sum // 2
return subset_sum(0, 0, target_sum)
# Example usage
nums = [1, 5, 11, 5]
print(canPartition_bruteforce(nums)) # Output: True
Explanation:
subset_sum
function recursively checks if there's a subset with a specific sum.False
because it's impossible to partition it into two equal subsets.However, this approach is very inefficient due to its exponential time complexity.
A more efficient approach is to use dynamic programming. We can create a DP table dp
where dp[i]
is True
if a subset with sum i
can be formed using the elements from nums
, and False
otherwise.
def canPartition(nums):
total_sum = sum(nums)
if total_sum % 2 != 0:
return False # If the total sum is odd, it can't be partitioned into two equal subsets.
target_sum = total_sum // 2
n = len(nums)
# dp[i] is True if a subset with sum i can be formed using elements from nums.
dp = [False] * (target_sum + 1)
dp[0] = True # An empty set has sum 0
for num in nums:
for i in range(target_sum, num - 1, -1):
dp[i] = dp[i] or dp[i - num]
return dp[target_sum]
# Example usage
nums = [1, 5, 11, 5]
print(canPartition(nums)) # Output: True
nums = [1, 2, 3, 5]
print(canPartition(nums)) # Output: False
Explanation:
False
.dp
of size target_sum + 1
.dp[0]
is initialized to True
because a subset with sum 0 can always be formed (an empty set).nums
and update the DP table. For each number, we iterate from target_sum
down to num
and check if dp[i - num]
is True
. If it is, it means that we can form a subset with sum i
by including the current number.nums
. This is because we generate all possible subsets.nums
and target_sum
is half of the total sum. The nested loops iterate through each element and each possible sum.target_sum + 1
.nums
is empty, the problem is not well-defined. However, for the purpose of this problem, we can assume an empty array cannot be partitioned into two equal subsets, so return False
.False
.def canPartition_edge_cases(nums):
if not nums:
return False # Empty array
if len(nums) == 1:
return False # Single element array
total_sum = sum(nums)
if total_sum % 2 != 0:
return False # Odd total sum
target_sum = total_sum // 2
n = len(nums)
dp = [False] * (target_sum + 1)
dp[0] = True
for num in nums:
for i in range(target_sum, num - 1, -1):
dp[i] = dp[i] or dp[i - num]
return dp[target_sum]