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.

Input: nums = [1,5,11,5]
Output: true
Explanation: Input array can be partitioned with two subsets [1, 5, 5] and [11].
Input: nums = [1,2,3,5]
Output: false
Explanation: Input array cannot be partitioned into two subsets.

Contents

Below are two important decisions to make in the solution intution.

In this approach, we will compute the sum of elements from input array and check if if it even or odd, if it is odd then return false, otherwise check if there is any subset possible with sum as sum/2.

Complexity Analysis:

Time complexity: Above code runs in O(2n) time where n is the size of the array, as we are creating a decision tree with two possibilities at each step.
Space complexity: O(n2) as we are making recursive loops n times and each time we are creating a new array and copying elements. We can avoid this by supplying just the array index to the recursive function and reduce the space complexity to O(n).

As you can see in above solution, sub problems will be repeated (for example, circled sub problems in the below diagram), so we can cahe the sub problem answer and use it.

recursive solution with memoization illustration import java.util.HashMap; public class PartitionEqualSubsetSum { /* optimized logic using memoization */ static boolean canPartitionUsingMemoization(int[] nums) { int sum = 0; for (int num : nums) { sum += num; } if (sum % 2 == 0) { HashMap memoize = new HashMap<>(); return canPartitionRecursive(nums, sum / 2); } return false; } static boolean canPartitionUsingMemoizationRec(int[] nums, int reminderArrayLength, int sum, HashMap cache) { if (sum == 0) { return true; } if ((reminderArrayLength == 0 && sum > 0) || sum < 0) { return false; } String key = reminderArrayLength + "-" + sum; if (cache.containsKey(key)) { return cache.get(key); } int reducedArrayLength = reminderArrayLength - 1; boolean ans = canPartitionUsingMemoizationRec(nums, reducedArrayLength, sum, cache) || canPartitionUsingMemoizationRec(nums, reducedArrayLength, sum - nums[reducedArrayLength], cache); cache.put(key, ans); return ans; } }
Complexity Analysis:

Time complexity: Above code runs in O(sum * n) time where n is the size of the array.
Space complexity: O(sum * n) as there may be need for cache every answer.

In this approach, we are going to compute all possible sums for each number in the array and store them in a Set. At the end return true if the set contains sum/2, false otherwise.

DP - memory optimized solution import java.util.HashMap; import java.util.HashSet; public class PartitionEqualSubsetSum { /* similar to above, but optimized */ static boolean canPartitionOptimizedUsingDP(int[] nums) { int sum = 0; for(int num: nums) { sum += num; } if(sum % 2 == 0) { return canPartitionMemoryOptimizedUsingDP(nums, sum/2); } return false; } static boolean canPartitionMemoryOptimizedUsingDP(int[] nums, int sum) { HashSet<Integer> memoized = new HashSet<>(); memoized.add(0); for(int i=0; i<nums.length; i++) { HashSet<Integer> nextSet = new HashSet<>(); for(Integer val : memoized) { nextSet.add(val+nums[i]); nextSet.add(val); } memoized = nextSet; } return memoized.contains(sum); } }
Complexity Analysis:

Time complexity: Above code runs in O(sum * n) time where n is the size of the array.
Space complexity: O(sum) as the max size of the set can be the sum.

Above implementations source code can be found at GitHub link for Java code