Search code examples
javaalgorithmbacktrackingsubset-sum

Subset Sum Problem: Returning a Variant of the Required Subset


Problem description:

Given a list of integers and a target sum, we're required to return another list containing Booleans. This Boolean list represents the subset that we're looking for.

Example:

Input: list (3, 34, 4, 12, 5, 2), target = 9.

Output: (false, false, true, false, true, false) (since 4+5 = 9; notice that this solution is not unique, but the problem only asks for one arbitrary solution).

My attempt:

I started with writing a method that checks if a solution even exists:

boolean subsetSumRec(List<Integer> list, int i, int sum) { //i is the index of the last element in list
    if(sum==0){
        return true;
    } else if(i<0 || sum<0){
        return false;
    }
    boolean include = subsetSumRec(list,i-1,sum-list.get(n));
    boolean exclude = subsetSumRec(list,i-1,sum);
    return include || exclude;
}

I made a new ArrayList (type: Boolean) resultList, that will be the output. My plan was to update resultList within the method subsetSumRec. It would be something like:

private boolean subsetSumRec(List<Integer> list, int i, int sum) {
    if(sum==0){
        return true;
    } else if(list.size()<=0 || sum<0){
        return false;
    }
    res.add(true);
    boolean include = subsetSumRec(list,i-1,sum-list.get(i));
    boolean exclude;
    if(include == false){
        res.remove(true);
        res.add(false);
        exclude = subsetSumRec(list, i - 1, sum);
    }
    return include || exclude;
}

This does not give the required result, but I don't see what's going wrong. How can this be optimized?

If updating resultList within subsetSumRec is not an option, then I'd have to get rid of the method that checks if there is a solution and use a backtracking algorithm (no dynamic programming!). I don't know how to start with the last one. Could somebody give me hint as to how to approach a backtracking algorithm for this problem (pseudocode?).

Thanks in advance.


Solution

  • Here's one example recursion in JavaScript. We return the second list if the solution is feasible, otherwise false.

    function f(A, S, B=new Array(A.length).fill(false), i=A.length - 1){
      if (A[i] == S){
        B[i] = true
        return B
      }
        
      if (i == 0){
        if (A[i] == S){
          B[i] = true
          return B
        }
        return false
      }
      
      if (A[i] <= S){
        let maybeB = f(A, S - A[i], B, i - 1)
        if (maybeB){
          B[i] = true
          return B
        }
      }
    
      return f(A, S, B, i - 1)
    }
    
    var A = [3, 34, 4, 12, 5, 2]
    var S = 9
    
    console.log(JSON.stringify(A))
    console.log(`Target: ${S}`)
    console.log(JSON.stringify(f(A, S)))
    
    S = 199
    console.log(`\nTarget: ${S}`)
    console.log(JSON.stringify(f(A, S)))