No.1300 LeetCode題目 “轉變數組後最接近目標值的數組和”

題目描述

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

解題思路

對所有可能的value值進行遍歷:(參考LeetCode官方解題思路)

  • value 的下界爲 0。這是因爲當 value = 0 時,數組的和爲 0。由於 target 是正整數,因此當 value 繼續減小時,數組的和也會隨之減小,且變爲負數(這個和等於 value * n,其中 n 是數組 arr 的長度),並不會比 value = 0 時更接近 target

  • value 的上界爲數組 arr 中的最大值。這是因爲當 value >= arr 時,數組中所有的元素都不變,因爲它們均不大於 value。由於我們需要找到最接近 target 的最小 value 值,因此我們只需將數組 arr 中的最大值作爲上界即可。

當我們確定了 value 值的上下界之後,就可以進行枚舉了。當枚舉到 value = x 時,我們需要將數組 arr 中所有小於等於 x 的值保持不變,所有大於 x 的值變爲 x。要實現這個操作,我們可以將數組 arr 先進行排序,隨後進行二分查找,找出數組 arr 中最小的比 x 大的元素 arr[i]。此時數組的和變爲:
在這裏插入圖片描述

具體代碼

class Solution {
public:
    int findBestValue(vector<int>& arr, int target) {
        //將數組進行排序(默認爲升序)
        sort(arr.begin(), arr.end());
        int n = arr.size();
        vector<int> prefix(n + 1);
        //計算前綴和
        for (int i = 1; i <= n; ++i) {
            prefix[i] = prefix[i - 1] + arr[i - 1];
        }
        //尋找數組中最大的元素,遍歷的範圍是從0到最大值。
        int r = *max_element(arr.begin(), arr.end());
        int ans = 0, diff = target;
        for (int i = 1; i <= r; ++i) {
            auto iter = lower_bound(arr.begin(), arr.end(), i);
            int cur = prefix[iter - arr.begin()] + (arr.end() - iter) * i;
            if (abs(cur - target) < diff) {
                ans = i;
                diff = abs(cur - target);
            }
        }
        return ans;
    }
};

性能結果

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章