Search code examples
javaarraysalgorithmsubset-sumarray-algorithms

How to fix my code to write a variant of the solution of the SubSet Sum problem?


Consider the Subset Sum (SUSU) problem, I need to write a variant of the solution shown in class which will also print which weights are aggregated to reach a given sum. For example, if:

sum=12;
int[] weights={1,7,9,3};

the output would be: 0011 That is, for each value in weights, we write "1" if it was added or "0" otherwise.

With the help of a friend, I wrote the following code:

    public static void main(String[] args) {

    int[] arr={9,1,7,3};
    System.out.println(Arrays.toString(SubsetSum(arr,12)));
}   

public static int[] SubsetSum(int[] arr, int sum){
    int[] output= new int[arr.length];
    return SubsetSum(arr,sum, 0, output);
}

public static int[] SubsetSum(int[] arr, int sum, int index, int[]weights){
    int[] output= new int[arr.length];
    if(sum==0)
        return weights;
    if(sum<0 | index>=arr.length)
        return output;
    weights[index]=0;
    int[] arr1= SubsetSum(arr,sum,index+1, weights);
    weights[index]=1;
    int[]arr2=SubsetSum(arr,sum-arr[index],index+1,weights);
    boolean isZero=true;
    for(int i=0; i<arr1.length & isZero; i=i+1)
        if(arr1[i]!=0)
            isZero=true;
    if(isZero)
        return arr2;
    else
        return arr1;
}

I expect the output of SubsetSum(arr,12) to be [1, 0, 0, 1] but the actual output is [0, 0, 0, 0]. I understand why it return this output from my code, but I don't know how to fix it.


Solution

  • I've changed method of returning result. Now used items are encoded in bits of used parameter.

    Ideone.

    Main prints indexes of items (or nothing in case of fail) - 1,2,3 for may example, i.e. 1 + 7 + 13

    I'm not familiar with Java, so represent result for better viewing (perhaps something like inttobinary)

    public static void main(String[] args) {
    
        int[] arr={9,1,7,13,3};
        int i = 0;
        int res = SubsetSum(arr, 21, 0, 0);
        while (res > 0) {
            if ((res & 1) > 0) 
                System.out.println(i);
            i++;
            res >>= 1;
        }       
    }   
    
    public static int SubsetSum(int[] arr, int sum, int index, int used){
        if(sum==0)
            return used;
        if(sum<0 | index>=arr.length)
            return 0;
           int a = SubsetSum(arr,sum,index+1, used);
           int b = SubsetSum(arr,sum-arr[index],index+1, used | (1 << index));
           if (a > 0)
              return a;
           else
              return b;
    }  
    }
    

    P.S. Flaws in your code:
    isZero is never changed.
    If you correct logic to return non-zero array, it will be filled with all 1's - perhaps because weights[index]=1; changes the same array instance through common reference (don't know Java terminology). In my code at every recursion level there is own used instance, and modigying its bits does not influence on values in other branches.