Question:
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.
Solution:
- Same question as Subset Sum Equal To K, just check if the total Sum of array can be divided by 2.
- If yes, then find a subset equal to that totalSum/2.
- If no, return false.
Recursive and DP Solution
DP solution TC and SC Time Complexity: O(n * target), where n is the number of elements in the array and target is half of the total sum. Space Complexity: O(target), since we are using a 1D array for the dynamic programming solution.
public class PartitionEqualSubsetSum {
public boolean canPartitionRecursive(int[] nums, int n, int target) {
// Base cases
if (target == 0) return true; // Found a subset with the target sum
if (n == 0 || target < 0) return false; // No more elements or target is invalid
// Choice to pick or not pick the current element nums[n-1]
boolean pick = canPartitionRecursive(nums, n - 1, target - nums[n - 1]); // Pick the element
boolean notPick = canPartitionRecursive(nums, n - 1, target); // Don't pick the element
// Return true if either pick or notPick leads to a valid subset
return pick || notPick;
}
public boolean canPartitionDP(int[] nums) {
int totalSum = 0;
// Calculate the total sum of the array
for (int num : nums) {
totalSum += num;
}
// If the total sum is odd, we can't partition it into two equal subsets
if (totalSum % 2 != 0) {
return false;
}
int target = totalSum / 2;
// Create a DP array to store whether a specific sum can be achieved
boolean[] dp = new boolean[target + 1];
dp[0] = true; // We can always achieve sum 0 by choosing no elements
// Iterate over each number in the array
for (int num : nums) {
// Update the DP array in reverse order
for (int i = target; i >= num; i--) {
dp[i] = dp[i] || dp[i - num]; // not pick || pick decision
}
}
// The answer will be stored in dp[target]
return dp[target];
}
public static void main(String[] args) {
PartitionEqualSubsetSum solution = new PartitionEqualSubsetSum();
int[] nums1 = {1, 5, 11, 5};
System.out.println(solution.canPartitionDP(nums1)); // Output: true
int[] nums2 = {1, 2, 3, 5};
System.out.println(solution.canPartitionDP(nums2)); // Output: false
}
}
Space Optimized
class Solution {
public boolean canPartition(int[] nums) {
int total = 0;
for(int i = 0; i < nums.length; i++){
total += nums[i];
}
if(total % 2 != 0){
return false;
}
int targetSum = total/2;
return subsetSumToK(nums.length, targetSum, nums);
}
public static boolean subsetSumToK(int n, int target, int arr[]){
//2-D which will contain indexes from 0 to n-1 and target from 0 to target
boolean[] prev = new boolean[target + 1];
boolean[] curr = new boolean[target + 1];
//Base case
prev[0] = true;//true for target zero
for(int j = 1; j <= target; j++){
prev[j] = false;
}
curr[0] = true; // A sum of 0 is always possible
for(int j = 1; j <= target; j++){
curr[j] = false; //baaki toh assign false, because these will be filled in the below loop
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= target; j++){
//If we don't include the current element
curr[j] = prev[j]; //Whatever the answer was till the last element
//if the current target is greater than current element then only we can subtract the target
//and check at the previous result of previous row if it was achieved or not.
if(j >= arr[i - 1]){
curr[j] = curr[j] || prev[j - arr[i - 1]];
}
}
prev = curr.clone();
}
return prev[target];
}
}