Problem Statement #

Given a set of positive numbers, determine if a subset exists whose sum is equal to a given number ‘S’.

Example 1: #
Input: {1, 2, 3, 7}, S=6
Output: True
The given set has a subset whose sum is '6': {1, 2, 3}
Example 2: #
Input: {1, 2, 7, 1, 5}, S=10
Output: True
The given set has a subset whose sum is '10': {1, 2, 7}
Example 3: #
Input: {1, 3, 4, 8}, S=6
Output: False
The given set does not have any subset whose sum is equal to '6'.

Basic Solution #

This problem follows the 0/1 Knapsack pattern and is quite similar to Equal Subset Sum Partition. A basic brute-force solution could be to try all subsets of the given numbers to see if any set has a sum equal to ‘S’.

So our brute-force algorithm will look like:

--NORMAL--

Since this problem is quite similar to Equal Subset Sum Partition, let’s jump directly to the bottom-up dynamic programming solution.

Bottom-up Dynamic Programming #

We’ll try to find if we can make all possible sums with every subset to populate the array dp[TotalNumbers][S+1].

For every possible sum ‘s’ (where 0 <= s <= S), we have two options:

  1. Exclude the number. In this case, we will see if we can get the sum ‘s’ from the subset excluding this number => dp[index-1][s]
  2. Include the number if its value is not more than ‘s’. In this case, we will see if we can find a subset to get the remaining sum => dp[index-1][s-num[index]]

If either of the above two scenarios returns true, we can find a subset with a sum equal to ‘s’.

Let’s draw this visually, with the example input {1, 2, 3, 7}, and start with our base case of size zero:

Created with Fabric.js 1.6.0-rc.1 num\sum 1 {1, 2} {1,2,3} {1,2,3,7} 0 T T T T 1 2 3 4 5 6
'0' sum can always be found through an empty set
1 of 10
Created with Fabric.js 1.6.0-rc.1 num\sum 1 {1, 2} {1,2,3} {1,2,3,7} 0 T T T T 1 T 2 F 3 F 4 F 5 F 6 F
With only one number, we can form a subset only when the required sum is equal to that number
2 of 10
Created with Fabric.js 1.6.0-rc.1 num\sum 1 {1, 2} {1,2,3} {1,2,3,7} 0 T T T T 1 T T 2 F 3 F 4 F 5 F 6 F
sum: 1, index:1=> (dp[index-1][sum] , as the 'sum' is less than the number at index '1' (i.e., 1 < 2)
3 of 10
Created with Fabric.js 1.6.0-rc.1 num\sum 1 {1, 2} {1,2,3} {1,2,3,7} 0 T T T T 1 T T 2 F T 3 F 4 F 5 F 6 F
sum: 2, index:1=> (dp[index-1][sum] || dp[index-1][sum-2])
4 of 10
Created with Fabric.js 1.6.0-rc.1 num\sum 1 {1, 2} {1,2,3} {1,2,3,7} 0 T T T T 1 T T 2 F T 3 F T 4 F 5 F 6 F
sum: 3, index:1=> (dp[index-1][sum] || dp[index-1][sum-2])
5 of 10
Created with Fabric.js 1.6.0-rc.1 num\sum 1 {1, 2} {1,2,3} {1,2,3,7} 0 T T T T 1 T T 2 F T 3 F T 4 F F 5 F F 6 F F
sum: 4-6 index:1=> (dp[index-1][sum] || dp[index-1][sum-2])
6 of 10
Created with Fabric.js 1.6.0-rc.1 num\sum 1 {1, 2} {1,2,3} {1,2,3,7} 0 T T T T 1 T T T 2 F T T 3 F T T 4 F F 5 F F 6 F F
sum: 1,2,3, index:2=> (dp[index-1][sum] || dp[index-1][sum-3])
7 of 10
Created with Fabric.js 1.6.0-rc.1 num\sum 1 {1, 2} {1,2,3} {1,2,3,7} 0 T T T T 1 T T T 2 F T T 3 F T T 4 F F T 5 F F 6 F F
sum: 4, index:2=> (dp[index-1][sum] || dp[index-1][sum-3])
8 of 10
Created with Fabric.js 1.6.0-rc.1 num\sum 1 {1, 2} {1,2,3} {1,2,3,7} 0 T T T T 1 T T T 2 F T T 3 F T T 4 F F T 5 F F T 6 F F T
sum: 5, 6, index:2=> (dp[index-1][sum] || dp[index-1][sum-3])
9 of 10
Created with Fabric.js 1.6.0-rc.1 num\sum 1 {1, 2} {1,2,3} {1,2,3,7} 0 T T T T 1 T T T T 2 F T T T 3 F T T T 4 F F T T 5 F F T T 6 F F T T
sum: 1-6, index:3=> (dp[index-1][sum] || dp[index-1][sum-7])
10 of 10

Code #

Here is the code for our bottom-up dynamic programming approach:

--NORMAL--

Output

0.497s

Can partition: True Can partition: True Can partition: False

Time and Space complexity #

The above solution has the time and space complexity of O(NS)O(N*S), where ‘N’ represents total numbers and ‘S’ is the required sum.

Challenge #

Can we improve our bottom-up DP solution even further? Can you find an algorithm that has O(S)O(S) space complexity?

Similar to the space optimized solution for 0/1 Knapsack

--NORMAL--

Output

0.473s

Can partition: True Can partition: True Can partition: False

Mark as Completed
←    Back
Equal Subset Sum Partition (medium)
Next    →
Minimum Subset Sum Difference (hard)