Leetcode 1300.轉變數組後最接近目標值的數組和(Sum of Mutated Array Closest to Target)

Leetcode 1300.轉變數組後最接近目標值的數組和

1 題目描述(Leetcode題目鏈接

  給你一個整數數組 arr 和一個目標值 target ,請你返回一個整數 value ,使得將數組中所有大於 value 的值變成 value 後,數組的和最接近 target (最接近表示兩者之差的絕對值最小)。

如果有多種使得和最接近 target 的方案,請你返回這些整數中的最小值。

請注意,答案不一定是 arr 中的數字。

輸入:arr = [4,9,3], target = 10
輸出:3
解釋:當選擇 value 爲 3 時,數組會變成 [3, 3, 3],和爲 9 ,這是最接近 target 的方案。
輸入:arr = [2,3,5], target = 10
輸出:5
輸入:arr = [60864,25176,27249,21296,20204], target = 56803
輸出:11361

提示:

  • 1 <= arr.length <= 10^4
  • 1 <= arr[i], target <= 10^5

2 題解

  本題使用前綴和+二分搜索,先將數組排序並記錄前綴和prefixprefix,規定二分查找的左邊界爲00,右邊界爲數組最大值,二分查找要替換的值。我們需要計算替換值後數組的和,因此我們可以再使用一個二分查找在數組中搜索最後一個小於替換值的元素的下標,這樣替換後數組的和就可以計算爲:
s=prefix[index]+mid(nindex) s = prefix[index] + mid*(n-index)
其中midmid爲替換值,indexindex爲最後一個小於替換值的元素的下標,nn爲數組長度。

  另外,這裏查找替換值的二分查找退出條件使用的是i<j1i<j-1,最後要判斷iijj到底哪一個是正確的返回值。

class Solution:
    def findBestValue(self, arr: List[int], target: int) -> int:
        arr.sort()
        n = len(arr)
        prefix = [0]
        s = 0
        for i in range(n):
            s += arr[i]
            prefix.append(s)
        i, j = 0, arr[-1]
        while i < j - 1:
            mid = (i + j) // 2
            index = bisect.bisect_left(arr, mid)
            s = prefix[index] + mid*(n - index)
            if s == target:
                return mid
            elif s > target:
                j = mid
            else:
                i = mid 
        a = bisect.bisect_left(arr, i)
        a = prefix[a] + i*(n - a)
        b = bisect.bisect_left(arr, j)
        b = prefix[b] + j*(n - b)
        return i if abs(a - target) <= abs(b - target) else j
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章