Reputation: 1661
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.
For example:
set = {1,2,5,7}
sum = 8
=> true
I actually solved the problem with this code:
public boolean isSubsetSum(int[] set, int sum) {
Arrays.sort(set);
boolean[][] memo = new boolean[set.length+1][sum+1];
for (int i = 0; i < memo.length; i++) {
memo[i][0] = true;
}
for (int i = 1; i < memo.length; i++) {
for (int j = 1; j < memo[i].length; j++) {
if (set[i-1] > j) {
memo[i][j] = memo[i-1][j];
} else {
memo[i][j] = memo[i-1][j] || memo[i-1][j-set[i-1]];
}
}
}
return memo[memo.length-1][memo[memo.length-1].length-1];
}
However, now I want to reconstruct all the possible combinations that form the given sum.
Is it possible to do that from my memoization matrix or do I have to do it differently?
Upvotes: 2
Views: 1019
Reputation: 2269
Make a new DP table called take[i][j]
which is boolean. It is true if you take the i-th
element for subset sum j
. You fill it concurrently with your normal memo table:
for (int i = 1; i < memo.length; i++) {
for (int j = 1; j < memo[i].length; j++) {
if (memo[i-1][j]){
//no need to take ith elements, first i-1 have sum j
take[i][j] = false;
memo[i][j] = true;
}
else if (j-set[i-1] >= 0 && memo[i-1][j-set[i-1]]){
//take ith element, and search for set of size j-set[i-1] in 1..i-1
take[i][j] = true;
memo[i][j] = true;
}
else{
//neither memo[i-1][j] or memo[i-1][j-set[i-1]] valid, so no way to make sum
take[i][j]=false;
memo[i][j]=false;
}
}
}
Finally, to reconstruct a solution, you start with:
int i =set.length
int j = sum
while (i>=0 && j>=0){
if (take[i][j]){
print(set[i])
j = j - set[i]
i=i-1
}
else{
i=i-1
}
}
You can generalize this for all sets of solutions.
Upvotes: 1