leetcode1300. 轉變數組後最接近目標值的數組和/二分法

題目

給你一個整數數組 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

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/sum-of-mutated-array-closest-to-target
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

基本思想:二分法

  • 對目標值進行二分
  • 如果取中間值,對應的數組的和比目標值大或者等於(因爲題目要求要找所有方案中最小的),那麼在[left,mid]中尋找,否則在[mid,right]中找。因爲mid也有可能成爲最終的結果,所以在取區間的時候不進行-1或者+1操作
  • 循環的條件是[left,right]中至少有三個數,對於最終的結果在left,right中分別判斷
  • 注意:當數組中的最大值不超過mid時,需要將區間縮放到[left,mid]
class Solution {
public:
    int findBestValue(vector<int>& arr, int target) {
        //二分法
        int l = 0, r = target, mid = (r - l) / 2 + l, cur;
        int m = *max_element(arr.begin(), arr.end());
        
        while(r - l > 1){
            mid = (r - l) / 2 + l;
            cur = 0;
            for(auto t : arr)
                cur += (t > mid) ? mid : t;
            if(m <= mid){
                r = mid;
                continue;
            }
            if(cur >= target){
                r = mid;
            }
            else if(cur < target){
                l = mid;
            }            
        }
        mid = l;
        cur = 0;
        for(auto t : arr)
            cur += (t > mid) ? mid : t;
        int div1 = abs(cur - target);
        mid = r;
        cur = 0;
        for(auto t : arr)
            cur += (t > mid) ? mid : t;
        int div2 = abs(cur - target);
        return (div1 > div2)? r : l;
    }
};

說明:

  • 對於上述二分的範圍,可以直接對數組的最大值進行二分
  • 對於每次循環求和,可以先將數組排序,藉助前綴和的思想來求當前情況下的和。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章