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

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

    This can be solve using BST.
    First sort the array say arr1
    To start create another arr2 with the last element of arr1 (remove this ele from arr1)

    Now:Repeat the steps till no swap happens.

    1. Check arr1 for an element which can be moved to arr2 using BST such that the diff is less MIN diff found till now.
    2. if we find an element move this element to arr2 and go to step1 again.
    3. if we don't find any element in above steps do steps 1 & 2 for arr2 & arr1. i.e. now check if we have any element in arr2 which can be moved to arr1
    4. continue steps 1-4 till we don't need any swap..
    5. we get the solution.

    Sample Java Code:

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    /**
     * Divide an array so that the difference between these 2 is min
     * 
     * @author shaikhjamir
     *
     */
    public class DivideArrayForMinDiff {
    
        /**
         * Create 2 arrays and try to find the element from 2nd one so that diff is
         * min than the current one
         */
    
        private static int sum(List arr) {
    
            int total = 0;
            for (int i = 0; i < arr.size(); i++) {
                total += arr.get(i);
            }
    
            return total;
        }
    
        private static int diff(ArrayList arr, ArrayList arr2) {
            int diff = sum(arr) - sum(arr2);
            if (diff < 0)
                diff = diff * -1;
            return diff;
        }
    
        private static int MIN = Integer.MAX_VALUE;
    
        private static int binarySearch(int low, int high, ArrayList arr1, int arr2sum) {
    
            if (low > high || low < 0)
                return -1;
    
            int mid = (low + high) / 2;
            int midVal = arr1.get(mid);
    
            int sum1 = sum(arr1);
            int resultOfMoveOrg = (sum1 - midVal) - (arr2sum + midVal);
            int resultOfMove = (sum1 - midVal) - (arr2sum + midVal);
            if (resultOfMove < 0)
                resultOfMove = resultOfMove * -1;
    
            if (resultOfMove < MIN) {
                // lets do the swap
                return mid;
            }
    
            // this is positive number greater than min
            // which mean we should move left
            if (resultOfMoveOrg < 0) {
    
                // 1,10, 19 ==> 30
                // 100
                // 20, 110 = -90
                // 29, 111 = -83
                return binarySearch(low, mid - 1, arr1, arr2sum);
            } else {
    
                // resultOfMoveOrg > 0
                // 1,5,10, 15, 19, 20 => 70
                // 21
                // For 10
                // 60, 31 it will be 29
                // now if we move 1
                // 71, 22 ==> 49
                // but now if we move 20
                // 50, 41 ==> 9
                return binarySearch(mid + 1, high, arr1, arr2sum);
            }
        }
    
        private static int findMin(ArrayList arr1) {
    
            ArrayList list2 = new ArrayList<>(arr1.subList(arr1.size() - 1, arr1.size()));
            arr1.remove(arr1.size() - 1);
            while (true) {
    
                int index = binarySearch(0, arr1.size(), arr1, sum(list2));
                if (index != -1) {
                    int val = arr1.get(index);
                    arr1.remove(index);
                    list2.add(val);
                    Collections.sort(list2);
                    MIN = diff(arr1, list2);
                } else {
                    // now try for arr2
                    int index2 = binarySearch(0, list2.size(), list2, sum(arr1));
                    if (index2 != -1) {
    
                        int val = list2.get(index2);
                        list2.remove(index2);
                        arr1.add(val);
                        Collections.sort(arr1);
    
                        MIN = diff(arr1, list2);
                    } else {
                        // no switch in both the cases
                        break;
                    }
                }
            }
    
            System.out.println("MIN==>" + MIN);
            System.out.println("arr1==>" + arr1 + ":" + sum(arr1));
            System.out.println("list2==>" + list2 + ":" + sum(list2));
            return 0;
        }
    
        public static void main(String args[]) {
    
            ArrayList org = new ArrayList<>();
            org = new ArrayList<>();
            org.add(1);
            org.add(2);
            org.add(3);
            org.add(7);
            org.add(8);
            org.add(10);
    
            findMin(org);
        }
    }
    

提交回复
热议问题