How to divide a set into two subsets such that difference between the sum of numbers in two sets is minimal?

前端 未结 18 738
攒了一身酷
攒了一身酷 2020-11-27 10:55

Given a set of numbers, divide the numbers into two subsets such that difference between the sum of numbers in two subsets is minimal.

T

18条回答
  •  我在风中等你
    2020-11-27 11:50

    I'll convert this problem to subset sum problem
    let's  take array int[] A = { 10,20,15,5,25,33 };
    it should be divided into {25 20 10} and { 33 20 } and answer is 55-53=2
    
    Notations : SUM == sum of whole array
                sum1 == sum of subset1
                sum2 == sum of subset1
    
    step 1: get sum of whole array  SUM=108
    step 2:  whichever way we divide our array into two part one thing will remain true
              sum1+ sum2= SUM
    step 3: if our intention is to get minimum sum difference then sum1 and sum2 should be near SUM/2 (example sum1=54 and sum2=54 then diff=0 )
    
    steon 4: let's try combinations
    
    
            sum1 = 54 AND sum2 = 54   (not possible to divide like this) 
            sum1 = 55 AND sum2 = 53   (possible and our solution, should break here)
            sum1 = 56 AND sum2 = 52  
            sum1 = 57 AND sum2 = 51 .......so on
            pseudo code
            SUM=Array.sum();
            sum1 = SUM/2;
            sum2 = SUM-sum1;
            while(true){
              if(subSetSuMProblem(A,sum1) && subSetSuMProblem(A,sum2){
               print "possible"
               break;
              }
             else{
              sum1++;
              sum2--;
             }
             }
    

    Java code for the same

    import java.util.ArrayList;
    import java.util.List;
    
    public class MinimumSumSubsetPrint {
    
    
    public static void main(String[] args) {
        int[] A = {10, 20, 15, 5, 25, 32};
        int sum = 0;
        for (int i = 0; i < A.length; i++) {
            sum += A[i];
        }
        subsetSumDynamic(A, sum);
    
    }
    
    private static boolean subsetSumDynamic(int[] A, int sum) {
        int n = A.length;
        boolean[][] T = new boolean[n + 1][sum + 1];
    
    
        // sum2[0][0]=true;
    
        for (int i = 0; i <= n; i++) {
            T[i][0] = true;
        }
    
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= sum; j++) {
                if (A[i - 1] > j) {
                    T[i][j] = T[i - 1][j];
                } else {
                    T[i][j] = T[i - 1][j] || T[i - 1][j - A[i - 1]];
                }
            }
        }
    
        int sum1 = sum / 2;
        int sum2 = sum - sum1;
        while (true) {
            if (T[n][sum1] && T[n][sum2]) {
                printSubsets(T, sum1, n, A);
                printSubsets(T, sum2, n, A);
                break;
            } else {
                sum1 = sum1 - 1;
                sum2 = sum - sum1;
                System.out.println(sum1 + ":" + sum2);
            }
        }
    
    
        return T[n][sum];
    }
    
    private static void printSubsets(boolean[][] T, int sum, int n, int[] A) {
        List sumvals = new ArrayList();
        int i = n;
        int j = sum;
        while (i > 0 && j > 0) {
            if (T[i][j] == T[i - 1][j]) {
                i--;
            } else {
                sumvals.add(A[i - 1]);
    
                j = j - A[i - 1];
                i--;
    
            }
        }
    
    
        System.out.println();
        for (int p : sumvals) {
            System.out.print(p + " ");
        }
        System.out.println();
    }
    
    
    }
    

提交回复
热议问题