Dynamic Programming | Set 25 (Subset Sum Problem)

Given a set of non-negative integers, and a value sum, determine if there is a subset of the given set with sum equal to given sum.

```Examples: set[] = {3, 34, 4, 12, 5, 2}, sum = 9
Output:  True  //There is a subset (4, 5) with sum 9.
```

We strongly recommend that you click here and practice it, before moving on to the solution.

Let isSubSetSum(int set[], int n, int sum) be the function to find whether there is a subset of set[] with sum equal to sum. n is the number of elements in set[].

The isSubsetSum problem can be divided into two subproblems
…a) Include the last element, recur for n = n-1, sum = sum – set[n-1]
…b) Exclude the last element, recur for n = n-1.
If any of the above the above subproblems return true, then return true.

Following is the recursive formula for isSubsetSum() problem.

```isSubsetSum(set, n, sum) = isSubsetSum(set, n-1, sum) ||
isSubsetSum(arr, n-1, sum-set[n-1])
Base Cases:
isSubsetSum(set, n, sum) = false, if sum > 0 and n == 0
isSubsetSum(set, n, sum) = true, if sum == 0
```

Following is naive recursive implementation that simply follows the recursive structure mentioned above.

C

```// A recursive solution for subset sum problem
#include <stdio.h>

// Returns true if there is a subset of set[] with sun equal to given sum
bool isSubsetSum(int set[], int n, int sum)
{
// Base Cases
if (sum == 0)
return true;
if (n == 0 && sum != 0)
return false;

// If last element is greater than sum, then ignore it
if (set[n-1] > sum)
return isSubsetSum(set, n-1, sum);

/* else, check if sum can be obtained by any of the following
(a) including the last element
(b) excluding the last element   */
return isSubsetSum(set, n-1, sum) ||
isSubsetSum(set, n-1, sum-set[n-1]);
}

// Driver program to test above function
int main()
{
int set[] = {3, 34, 4, 12, 5, 2};
int sum = 9;
int n = sizeof(set)/sizeof(set[0]);
if (isSubsetSum(set, n, sum) == true)
printf("Found a subset with given sum");
else
printf("No subset with given sum");
return 0;
}
```

Java

```// A recursive solution for subset sum problem
class subset_sum
{
// Returns true if there is a subset of set[] with sum
// equal to given sum
static boolean isSubsetSum(int set[], int n, int sum)
{
// Base Cases
if (sum == 0)
return true;
if (n == 0 && sum != 0)
return false;

// If last element is greater than sum, then ignore it
if (set[n-1] > sum)
return isSubsetSum(set, n-1, sum);

/* else, check if sum can be obtained by any of the following
(a) including the last element
(b) excluding the last element   */
return isSubsetSum(set, n-1, sum) ||
isSubsetSum(set, n-1, sum-set[n-1]);
}
/* Driver program to test above function */
public static void main (String args[])
{
int set[] = {3, 34, 4, 12, 5, 2};
int sum = 9;
int n = set.length;
if (isSubsetSum(set, n, sum) == true)
System.out.println("Found a subset with given sum");
else
System.out.println("No subset with given sum");
}
}/* This code is contributed by Rajat Mishra */

```

Output:
` Found a subset with given sum `

The above solution may try all subsets of given set in worst case. Therefore time complexity of the above solution is exponential. The problem is in-fact NP-Complete (There is no known polynomial time solution for this problem).

We can solve the problem in Pseudo-polynomial time using Dynamic programming. We create a boolean 2D table subset[][] and fill it in bottom up manner. The value of subset[i][j] will be true if there is a subset of set[0..j-1] with sum equal to i., otherwise false. Finally, we return subset[sum][n]

C

```// A Dynamic Programming solution for subset sum problem
#include <stdio.h>

// Returns true if there is a subset of set[] with sun equal to given sum
bool isSubsetSum(int set[], int n, int sum)
{
// The value of subset[i][j] will be true if there is a
// subset of set[0..j-1] with sum equal to i
bool subset[sum+1][n+1];

// If sum is 0, then answer is true
for (int i = 0; i <= n; i++)
subset[0][i] = true;

// If sum is not 0 and set is empty, then answer is false
for (int i = 1; i <= sum; i++)
subset[i][0] = false;

// Fill the subset table in botton up manner
for (int i = 1; i <= sum; i++)
{
for (int j = 1; j <= n; j++)
{
subset[i][j] = subset[i][j-1];
if (i >= set[j-1])
subset[i][j] = subset[i][j] ||
subset[i - set[j-1]][j-1];
}
}

/* // uncomment this code to print table
for (int i = 0; i <= sum; i++)
{
for (int j = 0; j <= n; j++)
printf ("%4d", subset[i][j]);
printf("\n");
} */

return subset[sum][n];
}

// Driver program to test above function
int main()
{
int set[] = {3, 34, 4, 12, 5, 2};
int sum = 9;
int n = sizeof(set)/sizeof(set[0]);
if (isSubsetSum(set, n, sum) == true)
printf("Found a subset with given sum");
else
printf("No subset with given sum");
return 0;
}
```

Java

```// A Dynamic Programming solution for subset sum problem
class subset_sum
{
// Returns true if there is a subset of set[] with sun equal to given sum
static boolean isSubsetSum(int set[], int n, int sum)
{
// The value of subset[i][j] will be true if there
// is a subset of set[0..j-1] with sum equal to i
boolean subset[][] = new boolean[sum+1][n+1];

// If sum is 0, then answer is true
for (int i = 0; i <= n; i++)
subset[0][i] = true;

// If sum is not 0 and set is empty, then answer is false
for (int i = 1; i <= sum; i++)
subset[i][0] = false;

// Fill the subset table in botton up manner
for (int i = 1; i <= sum; i++)
{
for (int j = 1; j <= n; j++)
{
subset[i][j] = subset[i][j-1];
if (i >= set[j-1])
subset[i][j] = subset[i][j] ||
subset[i - set[j-1]][j-1];
}
}

/* // uncomment this code to print table
for (int i = 0; i <= sum; i++)
{
for (int j = 0; j <= n; j++)
printf ("%4d", subset[i][j]);
printf("\n");
} */

return subset[sum][n];
}
/* Driver program to test above function */
public static void main (String args[])
{
int set[] = {3, 34, 4, 12, 5, 2};
int sum = 9;
int n = set.length;
if (isSubsetSum(set, n, sum) == true)
System.out.println("Found a subset with given sum");
else
System.out.println("No subset with given sum");
}
}/* This code is contributed by Rajat Mishra */

```

Output:
`Found a subset with given sum`

Time complexity of the above solution is O(sum*n).

Company Wise Coding Practice    Topic Wise Coding Practice

• vvkk

botton up manner
for (int i = 1; i <= sum; i++)
{
for (int j = 1; j = set[j-1])
subset[i][j] = subset[i][j] || subset[i – set[j-1]][j-1];
}
}

set should be renamed to subset at various places

• Guest

bool subset(int set[], int size, int sum)

{

for(int i = 0; i<size; i++)

{

if (set[i] <= sum)

sum -= set[i];

}

if(sum == 0)

return true;

else

return false;

}

• Guest

The first problem, if replaced by:

bool subset(int set[], int size, int sum)

{

for(int i = 0; i<size; i++)
{

if (set[i] <= sum)
sum -= set[i];

}

if(sum == 0)
return true;

else
return false;

}

…works well in all the cases I've tried so far.

What is it I'm missing here?

• vinnu

Can we try this sum – ar[i] = key search the key value using binary search the only problem is if sum = 8 and array has 2 fours. Can anyone suggest me is it works with tweaking of binary search?

• vrg

Isn’t the statement

if (set[n-1] > sum)
return isSubsetSum(set, n-1, sum);

in recursive solution redundant?
We are anyway handling both cases
(a) including the last element
(b) excluding the last element
in the statement
return isSubsetSum(set, n-1, sum) || isSubsetSum(set, n-1, sum-set[n-1]);

Can somebody explain why is it used?

• guest11

dont include the element which is already greater than sum

• guest11

it will avoid the last stmt where sum will become -ve ….that is not handled in the base case…….

or you can make an extra base case ….. if(sum <0) return 0;

• Vinay Singh

//this is my solution
//O(nlogn)

#include

int main()

{

int array[6]={3,6,4,1,5,2};

int n=6;

int i,j,t;

int f=0,u=5,k;

int sum=5;

int no;

//sorting of array(insertion)

for (i = 1 ; i 0 && array[j] < array[j-1]) {

t= array[j];

array[j] = array[j-1];

array[j-1] = t;

j–;

}

}

//actual code

for(i=0;i<6;i++)

{

no=array[f]+array[u];

if(sum no)

{

f++;

}

else if(sum==no)

{

printf(“n Subset: %d %d”,array[f],array[u]);

u–;

//break;

}

}

return 0;

}

• prashant jha

the code prints all the subsets for a given sum
http://ideone.com/DyULF2

• prashant jha

/*

void fun(int arr[],int *p,int index,int low,int high,int sum)

{

if((sumhigh))

return;

if(sum==0)

{

for(int i=0;i<index;i++)

{

cout<<p[i]<<" ";

}

cout<<"n";

return;

}

p[index]=arr[low];

fun(arr,p,index+1,low+1,high,sum-arr[low]);

fun(arr,p,index,low+1,high,sum);

}

int main()

{

int arr[]={3,1,5,2,4,6,7,8,9,12};

int n=sizeof(arr)/sizeof(arr[0]);

int *p=new int[n];

int sum;

cout<>sum;

fun(arr,p,0,0,n-1,sum);

return 0;

}
*/

• saurabh bhatia

anyone plz tell the algo if the array include negative numbers also…

• Jaime

I believe so:

1. Take the minimum value in the set, call it k.
2. Add each element in the set by the absolute value of k.
3. Add sum by the absolute value of k.
4. Perform the algorithm (and consider overflow).
5. Perform the inverse of steps 2 & 3.

• saurabh bhatia

thnx jamie but chk out this soln…..as i have used recursion 4 dis…
http://codingstreak.blogspot.in/

• Mike

This won’t work. Take the set (-5, 10) and see if any subset adds up to 5. We would convert (-5, 10) -> (0, 15) and 5->10. -5+10=5, but 0+15 != 10

• Justin Domingue

Add n times the absolute value of k to the sum and it works. 0+15 = 5+2*5.

• rishabh roy

could any one explain this part

for (int i = 1; i <= sum; i++)

{

for (int j = 1; j = set[j-1])

subset[i][j] = subset[i][j] || subset[i – set[j-1]][j-1];

}

}

• its_dark

We can use just a 1D array to store all the possible sums.Time complexity would still be O(sum*n), But space complexity O(sum);

``` int possiblesum[sum+1];; //initialize it with all zeroes for(int i=0; ix ;j++){ if(possiblesum[j-a[i]]==1) possiblesum[j]=1; } } ```

`If possiblesum[i]=1, sum=i is possible with a subset.`

• Shivam

What is x?

• its_dark

Edited !

• raviteja

I believe it is j– in the second for loop

• its_dark

yup..thanks

• Anurag

It seems possiblesum[0] needs to be initialized to 1, otherwise it may not work for a case where sum is equal to one of array element.

• its_dark

can’t we have a dp for this that takes purely polynomial time ?

• Vinodhini

Can we extend this DP logic to
1) print all the subsets of sum X
2) Find the number of subsets of sum X

If anyone could write a post on it, it would be very helpful

• its_dark

You can trace back down the path for a particular sum from the 2D array.

• sheetal

/// Sample Code here

for (int i = sum; i > 0; i–) {

for (int j = array.length; j > 0; j–) {

while (d[i][j] == false) {

if (i >= array[j]) {

i = i – array[j];

System.out.println(“[” + i + “,” + j + “]” + “—>” + array[j]);

}

while (i > 0 && j > 0 && d[i][j] != false) {

j–;

}

}

}

}

• sheetal

public boolean subsetSum(int[] array, int sum) {

boolean[][] d = new boolean[sum + 1][array.length + 1];

for (int i = 0; i <= array.length; i++) {

d[0][i] = true;

}

for (int i = 1; i <= sum; i++) {

d[i][0] = false;

}

for (int i = 1; i <= sum; i++) {

for (int j = 1; j = array[j – 1]) {

boolean x = d[i][j] || d[i – array[j – 1]][j – 1];

d[i][j] = x;

}

}

}

for (int i = 0; i <= sum; i++) {

for (int j = 0; j 0; i–) {

for (int j = array.length; j > 0; j–) {

while (d[i][j] == false) {

if (i >= array[j]) {

i = i – array[j];

System.out.println(“[” + i + “,” + j + “]” + “—>” + array[j]);

}

while (i > 0 && j > 0 && d[i][j] != false) {

j–;

}

}

}

}

return d[sum][array.length];

}

• Vinodhini

Can we extend this DP logic to
1) print the subsets of sum X
2) Find the number of subsets of sum X

If anyone could write a post on it, it would be very helpful

• Born Actor
``` ```
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int a[50];
int n;
int sum_final;
int lut[100][1000];
int function(int end, int sum);
int main()
{
cout<<"enter the size"<<endl;
cin>>n;
cout<<"enter the values"<<endl;
int i,j;
for(i=0;i<n;i++)
cin>>a[i];
cout<<"enter the sum"<<endl;
cin>>sum_final;
for(i=0;i<n;i++)
for(j=0;j<=sum_final;j++)
lut[i][j]=-1;
for(i=0;i<n;i++)
{
for(j=0;j<=sum_final;j++)
cout<<lut[i][j];
cout<<endl;
}
cout<<function(n-1,sum_final)<<endl;
}
int function(int end, int sum)
{
int p=0;
int q=0;
if(lut[end][sum]!=-1)
return lut[end][sum];
if(end>=0 && sum==0)
{
lut[end][sum]=1;
return lut[end][sum];
}
if(end<0 && sum>0)
return 0;
if(end>=0 && sum<0)
return 0;
p=function(end-1,sum-a[end]);
q=function(end-1,sum);
if(p or q)
lut[end][sum]=1;
else
lut[end][sum]=0;
return lut[end][sum];
}

``` ```
• shek8034

How to find all such subsets ?

• mani

cant we first sort it and then proceed like this–O(nlogn)

First substract the lastdigit from required sum and check the nearest number and substract it and again do it—O(n)
do it for all possible ways and check the min.

• hh

In the function why we assign subset[i][j] = subset[i][j-1].
Is it necessary to do so??
Why not subset[i][j] = subset[i][j-1]||subset[i-set[j-1]][j-1].

• Akshay

when original set is : {3, 34, 4, 12, 5, 2} and original sum is 0 then your method would return TRUE though actually it should return FALSE.

only an original set of type: {3, 34, 4, 0, 5, 2} should return TRUE if original sum is 0.

Following is the code WITHOUT Dynamic Programming to take care of the above.

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <Math.h>
#include <vector>

using namespace std;

bool SubsetSum(int set[], int n, int sum)
{
if(sum – set[n] == 0) return true;

if(n==0) return false;

if( set[n] > sum ) return SubsetSum(set, n-1, sum);

return SubsetSum(set, n-1, sum) || SubsetSum(set, n-1, sum-set[n]);

}

int main()
{
int set[] = {3,34,4,0,5,2};
int len = sizeof(set)/sizeof(int);
bool ans = SubsetSum(set, len-1, 0);

// system("PAUSE");
return 0;
}

• Akshay

For DYNAMIC PROGRAMMING the solution you have given needs a matrix of form: [n[sum], where n is number of elements in the original set.

But in the cases where n is very small (eg. 6) and sum is very large (eg. 1 million) then the space complexity will be too large. To avoid large space complexity n HASHTABLES can be used.

Values will be stored there like this: HASH[n].find(sum)

Time complexity will be O(1) for reading the value and storing it in the HASHTABLE.

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• mkamithkumar
``` ```
public class PartitionProblem {
public static void main(String args[]) {
int input[] = {1,1};
String result = partition(input);
System.out.println(result);

}

public static String partition(int[] input1) {
int n = input1.length;
String output = "";
// Checking input validations
if (n <= 0 || input1 == null) {
output = "Invalid";
} else {
for (int k = 0; k < input1.length; k++) {
if (input1[k] <= 0) {
output = "Invalid";
break;
}
}
}
if (output != "Invalid") {
// Calculate sum of the elements in array
int sum = 0;
for (int i = 0; i < n; i++)
sum += input1[i];
// If sum is odd, there cannot be two subsets with equal sum
if (sum % 2 != 0)
return "No";

// Find if there is subset with sum equal to half of total sum
if (isSubsetSum(input1, n, sum / 2))
return "Yes";
else
return "No";
} else {
return "Invalid";
}

}
// A utility function that returns true if there is a subset of arr[]
// with sun equal to given sum
static boolean isSubsetSum(int arr[], int n, int sum) {
// Base Cases
if (sum == 0)
return true;
if (n == 0 && sum != 0)
return false;
// If last element is greater than sum, then ignore it
if (arr[n - 1] > sum)
return isSubsetSum(arr, n - 1, sum);
/* else, check if sum can be obtained by any of the following
(a) including the last element
(b) excluding the last element
*/
return isSubsetSum(arr, n - 1, sum)|| isSubsetSum(arr, n - 1, sum - arr[n - 1]);
}
}

``` ```
• Leaner

Can somebody pls expalin what happens in this line
subset[i][j] = subset[i][j] || subset[i – set[j-1]][j-1];
I tried putting print statements, but couldnt get the catch of it.
Thanks.

Why can’t we build a binary tree and apply the pathSum algorithm to find the subset??? Pls correct me, if i m wrong.

Sorry that wont work…subset need not be contigious…

• Anirudh

How to modify the code above , if we are given negative numbers also in the array ?

• KSC

i think following will work..

take min of the given set and add |min| to every number in the set (essentially making every number positive), stop when sum=m*|min| (where m is size of the subset)..

• Treble
``` ```
bool has_subset_sum(int *a, int n, int sum)
{
bool *s = (bool *)malloc((sum+1)*sizeof(bool));
memset(s, 0, (sum+1)*sizeof(bool));
s[0] = true;
for (int i = 0; i < n; ++i) {
for (int j = 0; j <= sum; ++j) {
if (s[j] == true && a[i] + j <= sum) {
s[j + a[i]] = true;
}
}
}
bool ret = s[sum];
free(s);
return ret;
}
``` ```
• Alex
``` ```
/*
static boolean isSubsetSum(int array[], int n, int sum) {
Map<Integer,Boolean> map = new HashMap<Integer, Boolean>();
map.put(0, true);

for(int index =0; index < n; index++){

for(Entry<Integer, Boolean> entry: map.entrySet()){
Integer key = entry.getKey();
if(key+array[index] <= sum) {
}
}
map.put(number, true);
}

if(map.get(sum) != null){
return true;
}
}

return false;
} */
``` ```
• jobin

what you have done is similar to DP, but it won’t work because you have neglected the base case

``` ```
int isSubsetSum(int set[], int n, int sum)
{
int isSum[sum+1];
int i, j;
isSum[0] = 1;
for(i=0;i<n;i++)
{
isSum[set[i]] = 1;
}
for (i = 0; i < n; i++) {
for (j = sum - set[i]; j >= 0; j--) {
if (isSum[j] == 1)
isSum[j+set[i]] = 1;
}
if (isSum[sum] == 1)
return 1;
}

return 0;
}

``` ```
• Kanhaiya

I think we can apply non-dynamic solution for this particular problem. The below code is for sorted list. We can sort the array in with some good sort technique and then use the below.

#include <iostream>

using namespace std;
//Please note that list is sorted
bool sum_in_list (int list[], int n, int sum)
{
int i = 0;
int j = n – 1;

while (i < n && i < j)
{
if (sum == list[i] || sum == list[j] || sum == (list[i] + list[j]))
{
return true;
}

if (sum < list[j] || sum < (list[i] + list[j]))
{
j–;
continue;
}
else
{
i++;
continue;
}
return false;
}
}
int main ()
{
int list[] = { 1, 2, 3, 4, 5 };

cout << "sum " << sum_in_list (list, 5, 5) << endl;
cout << "sum " << sum_in_list (list, 5, 1) << endl;
cout << "sum " << sum_in_list (list, 5, 6) << endl;
cout << "sum " << sum_in_list (list, 5, 8) << endl;
return 0;
}

• Kanhaiya

As pointed out by Karthik, its not correct solution for subset problem. Please ignore this solution.

• Kanhaiya

I think for this particular problem, dynamic programming may not be best solution. Can we do something like this:
1. sort the array
2. Keep pointers from start and end. Check if sum of those make it to the required sum, if not modify ptrs accordkingly.

• Kartik

@Kanhaiya : This solution works well when we need to find two elements with sum equal to given sum. But here the problem is to find a subset (there may be any number of elements from array)

• Kanhaiya

got that sorry for not reading it properly.

• I was just messing around with something like this! Here’s a one-liner in haskell:

import Data.List

isSubsetSum xs n = any (== n) . map sum . nub . concatMap subsequences . permutations \$ xs

• Prakhar Jain

I’m indebted to bcurcio for this code.
http://www.codechef.com/viewsolution/1559359

``` ```
#include <stdio.h>

int isSubsetSum(int set[], int n, int sum)
{
int isSum[sum+1];
int i, j;
isSum[0] = 1;
for (i = 0; i < n; i++) {
for (j = sum - set[i]; j >= 0; j--) {
if (isSum[j] == 1)
isSum[j+set[i]] = 1;
}
if (isSum[sum] == 1)
return 1;
}

return 0;
}

int main()
{
int set[] = {3, 34, 4, 12, 5, 2};
int sum = 9;
int n = sizeof(set)/sizeof(set[0]);
if (isSubsetSum(set, n, sum) == 1)
printf("Found a subset with given sum");
else
printf("No subset with given sum");
return 0;
}
``` ```
• Kartik

@Prakhar Jain: Thanks for suggesting a space efficient solution. Could you please add few more word about the working and correctness of code?

• Prakhar Jain
``` ```
#include <stdio.h>

int isSubsetSum(int set[], int n, int sum)
{
int isSum[sum+1];
int i, j;
isSum[0] = 1;
for (i = 0; i < n; i++) {
for (j = sum - set[i]; j >= 0; j--) {
if (isSum[j] == 1)
isSum[j+set[i]] = 1;
}
if (isSum[sum] == 1)
return 1;
}

return 0;
}

int main()
{
int set[] = {3, 34, 4, 12, 5, 2};
int sum = 9;
int n = sizeof(set)/sizeof(set[0]);
if (isSubsetSum(set, n, sum) == 1)
printf("Found a subset with given sum");
else
printf("No subset with given sum");
return 0;
}
``` ```
• ajay

The array isSum should be initialized before being used in the if condition in the inner for loop else it may lead to undefined behavior.

• jobin

for(i=0;i<n;i++)
{
isSum[set[i]] = 1;
}

• GR

@jobin – isSum of size sum+1, set[i] could be greater than sum.
Ex: isSum[set[1]] => isSum[34] => boooom

so better to initialization as following

``` ```
isSum[0] = 1;
for(i=1; i<=sum; i++)
{
isSum[i] = 0;
}
``` ```