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

前端 未结 18 735
攒了一身酷
攒了一身酷 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:45

    Please check this logic which I have written for this problem. It worked for few scenarios I checked. Please comment on the solution, Approach :

    1. Sort the main array and divide it into 2 teams.
    2. Then start making the team equal by shift and swapping elements from one array to other, based on the conditions mentioned in the code.

    If the difference is difference of sum is less than the minimum number of the larger array(array with bigger sum), then shift the elements from the bigger array to smaller array.Shifting happens with the condition, that element from the bigger array with value less than or equal to the difference.When all the elements from the bigger array is greater than the difference, the shifting stops and swapping happens. I m just swapping the last elements of the array (It can be made more efficient by finding which two elements to swap), but still this worked. Let me know if this logic failed in any scenario.

    public class SmallestDifference {
    static int sum1 = 0, sum2 = 0, diff, minDiff;
    private static List minArr1;
    private static List minArr2;
    private static List biggerArr;
    
    /**
     * @param args
     */
    public static void main(String[] args) {
        SmallestDifference sm = new SmallestDifference();
        Integer[] array1 = { 2, 7, 1, 4, 5, 9, 10, 11 };
        List array = new ArrayList();
        for (Integer val : array1) {
            array.add(val);
        }
        Collections.sort(array);
        CopyOnWriteArrayList arr1 = new CopyOnWriteArrayList<>(array.subList(0, array.size() / 2));
        CopyOnWriteArrayList arr2 = new CopyOnWriteArrayList<>(array.subList(array.size() / 2, array.size()));
        diff = Math.abs(sm.getSum(arr1) - sm.getSum(arr2));
        minDiff = array.get(0);
        sm.updateSum(arr1, arr2);
        System.out.println(arr1 + " : " + arr2);
        System.out.println(sum1 + " - " + sum2 + " = " + diff + " : minDiff = " + minDiff);
        int k = arr2.size();
        biggerArr = arr2;
        while (diff != 0 && k >= 0) {
            while (diff != 0 && sm.findMin(biggerArr) < diff) {
                sm.swich(arr1, arr2);
                int sum1 = sm.getSum(arr1), sum2 = sm.getSum(arr2);
                diff = Math.abs(sum1 - sum2);
                if (sum1 > sum2) {
                    biggerArr = arr1;
                } else {
                    biggerArr = arr2;
                }
                if (minDiff > diff || sm.findMin(biggerArr) > diff) {
                    minDiff = diff;
                    minArr1 = new CopyOnWriteArrayList<>(arr1);
                    minArr2 = new CopyOnWriteArrayList<>(arr2);
                }
                sm.updateSum(arr1, arr2);
                System.out.println("Shifting : " + sum1 + " - " + sum2 + " = " + diff + " : minDiff = " + minDiff);
            }
            while (k >= 0 && minDiff > array.get(0) && minDiff != 0) {
                sm.swap(arr1, arr2);
                diff = Math.abs(sm.getSum(arr1) - sm.getSum(arr2));
                if (minDiff > diff) {
                    minDiff = diff;
                    minArr1 = new CopyOnWriteArrayList<>(arr1);
                    minArr2 = new CopyOnWriteArrayList<>(arr2);
                }
                sm.updateSum(arr1, arr2);
                System.out.println("Swapping : " + sum1 + " - " + sum2 + " = " + diff + " : minDiff = " + minDiff);
                k--;
            }
            k--;
        }
        System.out.println(minArr1 + " : " + minArr2 + " = " + minDiff);
    }
    
    private void updateSum(CopyOnWriteArrayList arr1, CopyOnWriteArrayList arr2) {
        SmallestDifference sm1 = new SmallestDifference();
        sum1 = sm1.getSum(arr1);
        sum2 = sm1.getSum(arr2);
    }
    
    private int findMin(List biggerArr2) {
        Integer min = biggerArr2.get(0);
        for (Integer integer : biggerArr2) {
            if(min > integer) {
                min = integer;
            }
        }
        return min;
    }
    
    private int getSum(CopyOnWriteArrayList arr) {
        int sum = 0;
        for (Integer val : arr) {
            sum += val;
        }
        return sum;
    }
    
    private void swap(CopyOnWriteArrayList arr1, CopyOnWriteArrayList arr2) {
        int l1 = arr1.size(), l2 = arr2.size(), temp2 = arr2.get(l2 - 1), temp1 = arr1.get(l1 - 1);
        arr1.remove(l1 - 1);
        arr1.add(temp2);
        arr2.remove(l2 - 1);
        arr2.add(temp1);
        System.out.println(arr1 + " : " + arr2);
    }
    
    private void swich(CopyOnWriteArrayList arr1, CopyOnWriteArrayList arr2) {
        Integer e;
        if (sum1 > sum2) {
            e = this.findElementJustLessThanMinDiff(arr1);
            arr1.remove(e);
            arr2.add(e);
        } else {
            e = this.findElementJustLessThanMinDiff(arr2);
            arr2.remove(e);
            arr1.add(e);
        }
        System.out.println(arr1 + " : " + arr2);
    }
    
    private Integer findElementJustLessThanMinDiff(CopyOnWriteArrayList arr1) {
        Integer e = arr1.get(0);
        int tempDiff = diff - e;
        for (Integer integer : arr1) {
            if (diff > integer && (diff - integer) < tempDiff) {
                e = integer;
                tempDiff = diff - e;
            }
        }
        return e;
    }
    

    }

提交回复
热议问题