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$

链接:https://leetcode-cn.com/problems/sum-of-mutated-array-closest-to-target

题解

1、排序 + 枚举 + 二分查找 + 前缀和

将数组从小到大排序,求得前缀和数组后,进行枚举每一个可能的值i,二分查找i在排序数组中的位置,根据该位置,计算处理后的数组和,求出一个最接近target的i。

class Solution {
    public int findBestValue(int[] arr, int target) {
        // 排序
        Arrays.sort(arr);
        int n = arr.length;
        // 初始化前缀和数组
        int[] prefix = new int[n + 1];
        for (int i = 1;i <= n; ++i) {
            prefix[i] = prefix[i-1] + arr[i-1];
        }
        // 二分查找
        // 根据数组元素的值进行二分查找
        int r = arr[n - 1];
        int ans = 0, diff = target;
        // 遍历每一个值[1,max],取最优
        for (int i = 1;i <= r;++i) {
            int index = Arrays.binarySearch(arr,i);
            if (index < 0) {
                index  = -index - 1;
            }

            int cur = prefix[index] + (n - index) * i;
            if (Math.abs(cur - target) < diff) {
                ans = i;
                diff = Math.abs(cur - target);
            }
        }
        return ans;
    }
}

双重二分查找

二分查找一个value_lower,其处理后的数组和最接近target且不小于target;
二分查找一个value_upper,其处理后的数组和最接近target且大于target;

class Solution {
    public int findBestValue(int[] arr, int target) {
        // 排序
        Arrays.sort(arr);
        int n = arr.length;
        // 求前缀合
        int[] prefix = new int[n + 1];
        for (int i = 1; i <= n; ++i) {
            prefix[i] = prefix[i - 1] + arr[i - 1];
        }
        // 二分查找
        int l = 0, r = arr[n - 1], ans = -1;
        while (l <= r) {
            int mid = (l + r) / 2;
            int index = Arrays.binarySearch(arr, mid);
            if (index < 0) {
                index = -index - 1;
            }
            int cur = prefix[index] + (n - index) * mid;
            if (cur <= target) {
                ans = mid;
                l = mid + 1;
            }
            else {
                r = mid - 1;
            }
        }
        int chooseSmall = check(arr, ans);
        int chooseBig = check(arr, ans + 1);
        return Math.abs(chooseSmall - target) <= Math.abs(chooseBig - target) ? ans : ans + 1;
    }

    public int check(int[] arr, int x) {
        int ret = 0;
        for (int num : arr) {
            ret += Math.min(num, x);
        }
        return ret;
    }
}

// 作者:LeetCode-Solution
// 链接:https://leetcode-cn.com/problems/sum-of-mutated-array-closest-to-target/solution/bian-shu-zu-hou-zui-jie-jin-mu-biao-zhi-de-shu-zu-/

从平均值开始,枚举,直到数组和大于目标值

该解法忽略了一个情况,就是数组的最大值小于平均值的情况,这时候,要返回最大值。

class Solution {
    public int findBestValue(int[] arr, int target) {
        int preSum = 0, sum = 0, flag = 0, cur = target/arr.length;//cur为枚举变量,从平均值开始可以降低一点时间复杂度
        while(true){
            preSum = sum;
            sum = 0;
            flag = 0;
            for(int i = 0; i < arr.length; i++){
                if(arr[i] > cur) sum += cur;
                else{
                    sum += arr[i];
                    flag++;//记录跳入此分支的次数
                }
            }
            if(flag == arr.length) return cur;//当数组中的数全比cur小,直接返回当前cur值就好(相当于数组中的最大值)
            if(sum >= target) break;
            cur++;
            
        }
        return Math.abs(target-preSum) > Math.abs(target-sum) ? cur : cur - 1;
    }
}

// 作者:VincentHwong
// 链接:https://leetcode-cn.com/problems/sum-of-mutated-array-closest-to-target/solution/chun-bao-li-mei-xiang-dao-yong-er-fen-ye-bu-xu-yao/

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1056615746@qq.com

💰

Title:1300、转变数组后最接近目标值的数组和

Count:930

Author:攀登

Created At:2020-07-26, 00:19:44

Updated At:2024-06-15, 15:52:32

Url:http://jiafeimao-gjf.github.io/2020/07/26/1300%E3%80%81%E8%BD%AC%E5%8F%98%E6%95%B0%E7%BB%84%E5%90%8E%E6%9C%80%E6%8E%A5%E8%BF%91%E7%9B%AE%E6%A0%87%E5%80%BC%E7%9A%84%E6%95%B0%E7%BB%84%E5%92%8C/

Copyright: 'Attribution-non-commercial-shared in the same way 4.0' Reprint please keep the original link and author.

×

Help us with donation