[1300. 转变数组后最接近目标值的数组和]

[1300. 转变数组后最接近目标值的数组和]

给你一个整数数组 arr 和一个目标值 target ,请你返回一个整数 value ,使得将数组中所有大于 value 的值变成 value 后,数组的和最接近 target (最接近表示两者之差的绝对值最小)。

如果有多种使得和最接近 target 的方案,请你返回这些整数中的最小值。

请注意,答案不一定是 arr 中的数字。

示例 1:

输入:arr = [4,9,3], target = 10
输出:3
解释:当选择 value 为 3 时,数组会变成 [3, 3, 3],和为 9 ,这是最接近 target 的方案。

示例 2:

输入:arr = [2,3,5], target = 10
输出:5

示例 3:

输入:arr = [60864,25176,27249,21296,20204], target = 56803
输出:11361

提示:

  • 1 <= arr.length <= 10^4
  • 1 <= arr[i], target <= 10^5
public int findBestValue(int[] arr, int target) {
    //从小到大排序
        Arrays.sort(arr);
    //计算前缀和
        int sum = 0;
	
        for (int i = 0; i < arr.length; i++) {
            //计算还未加上部分的最佳平均值,当小数部分等于0.5时,只能向左取值
            int x = (int)( (double)(target-sum)/(arr.length-i)+0.499999);
			
            //如果平均值小于等于当前值,也就是说后续的值只会越来越大,截断值为当前平均值最接近target
            if(x <= arr[i]){
                return x;
            }
            sum += arr[i];
        }
    //此时说明数组所有值相加小于target,返回数组最大值
        return arr[arr.length-1];
    }

另一种思路是二分查找截断值,可以很容易找到两个边界,target/arr.size()arr.max(),如果target/arr.size() 大于 arr.max(),说明数组和小于target,返回arr.max()

 public int findBestValue(int[] arr, int target) {

        int average = (int)( (double)target/arr.length+0.49999);
        int max = 0;
        for (int i : arr) {
            if(i > max) {
                max = i;
            }
        }

        if(max < average){
            return max;
        }

        int sum = 0;
        while (average < max){
            sum = 0;
            int median = (average+max)/2;
            for (int i : arr) {
                if(i > median) {
                    sum += median;
                }else {
                    sum += i;
                }
            }
            if(sum <= target){
                average = median+1;
            }else {
                max = median;
            }
        }
        sum = 0;
        for (int i : arr) {
            if(i > average){
                sum += average;
            }else {
                sum += i;
            }
        }

        int tmp = 0;
        for (int i : arr) {
            if(i > average-1){
                tmp += average-1;
            }else {
                tmp += i;
            }
        }

        if(Math.abs(target - tmp) >Math.abs(sum - target)){
            return average;
        }else {
            return average-1;
        }
    }
因为我喜欢追寻过程中的自己
原文地址:https://www.cnblogs.com/IzuruKamuku/p/14359769.html