如何将整数范围分成两个相等的部分

How to separate range of integers into two equal parts

我有一个像这样的整数数组

int [] num = {5, 8, 1, 1, 2, 3, 2}

我想把它分成2部分,这样2组的总数会尽可能相等:(输出)

SET 1: 5 Piece(s)
1
1
2
2
5
Total: 11

SET 2: 2 Piece(s)
8
3
Total: 11

另一个例子是

int [] num = {4, 6, 1, 2, 3, 3, 4}

输出如下:

SET 1: 3 Piece(s)
3
4
4
Total: 11

SET 2: 4 Piece(s) 
6
1
2
3
Total: 12

有什么帮助吗? =) 谢谢

有一个 for 循环像这样循环:

int sum =0:
for(int I=0; I<num.length/2; I++){
System.out.println(num[i]);
sum=sum+num[i];
}
System.out.println(sum);

(写于ipad 如有错误请见谅。

如果数组不是太长,尝试一个懒惰的解决方案:暴力破解。由于您需要的只是将它分成两组,因此您需要检查 2^n 种可能性,因为一个数字要么在第一组中,要么不在(即在第二组中)。

这是我刚写的示例代码:

public static int[][] bruteForce(int[] input) {
    int n = input.length;
    int[][] res = new int[2][n];
    int minVal = Integer.MAX_VALUE;
    int iMinVal = 0;
    int limit = (int) Math.pow(2, n);

    for (int i = 0; i < limit; i++) {
        int v = i;
        int diff = 0;
        for (int j = 0; j < n; j++) {
            diff = diff + ((v & 1) == 0 ? +1 : -1) * input[j];
            v = v >> 1;
        }
        if (Math.abs(diff) < minVal) {
            iMinVal = i;
            minVal = Math.abs(diff);
        }
    }

    int a = 0, b = 0;
    for (int i = 0; i < n; i++) {
        if ((iMinVal & 1) == 0) {
            res[0][a++] = input[i];
        } else {
            res[1][b++] = input[i];
        }
        iMinVal = iMinVal >> 1;
    }

    return res;
}

public static void main(String[] args) {
    int[] num = {5 ,8 ,1 ,1 ,2 ,3 ,2};
    int[] num2 = {4, 6, 1, 2, 3, 3, 4};

    int[][] r = bruteForce(num);
    System.out.println("First example:");
    System.out.println(Arrays.toString(r[0])+ ", sum = "+Arrays.stream(r[0]).sum());
    System.out.println(Arrays.toString(r[1])+ ", sum = "+Arrays.stream(r[1]).sum());

    r = bruteForce(num2);
    System.out.println("Second example:");
    System.out.println(Arrays.toString(r[0])+ ", sum = "+Arrays.stream(r[0]).sum());
    System.out.println(Arrays.toString(r[1])+ ", sum = "+Arrays.stream(r[1]).sum());
}

输出:

First example:
[5, 1, 3, 2, 0, 0, 0], sum = 11
[8, 1, 2, 0, 0, 0, 0], sum = 11
Second example:
[2, 3, 3, 4, 0, 0, 0], sum = 12
[4, 6, 1, 0, 0, 0, 0], sum = 11

如果数组的长度很大,那么我想尝试一些智能暴力或其他方法。例如,将数组按非升序排序,然后从最大值开始,将每个值放入总和较小的数组中,在当前情况下给出正确答案:

public static int[][] alternative(int[] input) {
    int n = input.length;
    int[][] res = new int[2][n];

    int[] input0 = Arrays.copyOf(input, n);

    Arrays.sort(input0);

    System.out.println("Input: "+Arrays.toString(input)+", ordered: "+Arrays.toString(input0));

    int sum1 = 0, sum2 = 0;
    int a = 0, b = 0;

    for (int i = n-1; i >= 0; i--) {
        if (sum1 <= sum2) {
            res[0][a++] = input0[i];
            sum1 = sum1 + input0[i];
            System.out.println("Adding "+input0[i]+" into set 1 ==> Sum1 = "+sum1);
        } else {
            res[1][b++] = input0[i];
            sum2 = sum2 + input0[i];
            System.out.println("Adding "+input0[i]+" into set 2 ==> Sum2 = "+sum2);
        }
    }
    return res;
}

输出:

First example:
Input: [5, 8, 1, 1, 2, 3, 2], ordered: [1, 1, 2, 2, 3, 5, 8]
Adding 8 into set 1 ==> Sum1 = 8
Adding 5 into set 2 ==> Sum2 = 5
Adding 3 into set 2 ==> Sum2 = 8
Adding 2 into set 1 ==> Sum1 = 10
Adding 2 into set 2 ==> Sum2 = 10
Adding 1 into set 1 ==> Sum1 = 11
Adding 1 into set 2 ==> Sum2 = 11
[8, 2, 1, 0, 0, 0, 0], sum = 11
[5, 3, 2, 1, 0, 0, 0], sum = 11

Second example:
Input: [4, 6, 1, 2, 3, 3, 4], ordered: [1, 2, 3, 3, 4, 4, 6]
Adding 6 into set 1 ==> Sum1 = 6
Adding 4 into set 2 ==> Sum2 = 4
Adding 4 into set 2 ==> Sum2 = 8
Adding 3 into set 1 ==> Sum1 = 9
Adding 3 into set 2 ==> Sum2 = 11
Adding 2 into set 1 ==> Sum1 = 11
Adding 1 into set 1 ==> Sum1 = 12
[6, 3, 2, 1, 0, 0, 0], sum = 12
[4, 4, 3, 0, 0, 0, 0], sum = 11

对于输出中的 0,您可以编写一个简单的函数来创建一个没有 0 的新数组。

我们应该尝试所有组合。例如,如果数组是 (1,1,100,100),则答案是 (100,1) (100,1)。如果数组是 (1,1,50,100),则答案是 (1,1,50) (100)。我不认为这有任何捷径。如果数组有 N 个元素,那么我们将尝试所有组合 (Nc1, NcN01), (Nc2, NcN-2) .. 等等。然后找出他们之间的差异最小