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];
}
}