两个集合最接近的累加和

发布时间 2023-11-27 17:57:44作者: TerryChenForYou

给定一个正数数组arr,

请把arr中所有的数分成两个集合,尽量让两个集合的累加和接近

返回最接近的情况下,较小集合的累加和

暴力递归

分析题干:

1:将arr数组分成两个集合,并且两个集合的累加和尽量的接近。

2:返回最接近情况下的最小集合累加和。

那就假设arr数组中元素的累加和是sum,让两个集合的累加和都接近sum / 2,自然两个集合的累加和就接近了。

在两个集合都接近sum / 2时,可能会出现一个超过sum / 2一点,另一个小于sum / 2一点,因为返回最接近情况下的最小集合累

加和。所以就返回小于sum / 2一点的这个就好。

所以递归的时候我们找累加和小于sum / 2一点的返回。这也就是

	if (arr[index] <= rest) { //    ---注意---
        p2 = arr[index] + process(arr, index + 1, rest - arr[index]);
     }

这个条件加上的原因。

	public static int right(int[] arr) {
        if (arr == null || arr.length == 0) {
            return 0;
        }
        //sum -> 累加和
        int sum = 0;
        for (int nub : arr) {
            sum += nub;
        }
        //因为两个集合是二元相对的所以找到一个就相当于找到另一个了。
        int a = process(arr, 0, sum / 2);
        return a;
    }

    //从index = 0位置出发,找到不超过但是最接近rest的累计和,然后返回该累计和。
    //同样这里要求找到不超过但是最接近rest的累加和。同样是二元相对的,找的这个就对应找到另一个。
    public static int process(int[] arr, int index, int rest) {
        if (index == arr.length) {
            return 0;
        }
        //不要index位置
        int p1 = process(arr, index + 1, rest);
        //要index位置
        int p2 = 0;
        if (arr[index] <= rest) { //    ---注意---
            p2 = arr[index] + process(arr, index + 1, rest - arr[index]);
        }
        return Math.max(p1, p2);
    }

dp方法

public static int dp(int[] arr) {
    if (arr == null || arr.length == 0) {
        return 0;
    }
    //sum -> 累加和
    int sum = 0;
    for (int nub : arr) {
        sum += nub;
    }
    int N = arr.length;
    int rest = sum / 2;
    int[][] dp = new int[N + 1][rest + 1];
    for (int i = 0; i <= rest; i++) {
        dp[N][i] = 0;
    }
    for (int H = N - 1; H >= 0; H--) {
        for (int L = 0; L <= rest; L++) {
            //不要index位置
            int p1 = dp[H + 1][L];
            //要index位置
            int p2 = 0;
            if (arr[H] <= L) {
                p2 = arr[H] + dp[H + 1][L - arr[H]];
            }
            dp[H][L] = Math.max(p1, p2);
        }
    }
    return dp[0][rest];
}