【LeetCode每日一题】2020.6.14 1300. 转变数组后最接近目标值的数组和

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

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

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

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

示例:

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

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

分析:

​ (1)题目说-会将数组中所有大于value的值变成value,提示可以将数组arr进行排序。这样就方便我们统计那些数组元素保留原值,其他元素变为value。这样得到一个公式arr[i] * times + res(times,大于value的元素个数,res,小于value的元素的值)。就可以拿这个值来与target比较。

​ (2)上一步得到了比较的公式。进一步思考如何比较。如果不断+1遍历,对于示例二来说就非常的慢。因此可以用二分法来进行搜索。

​ (3)二分搜索区间:

​ 对于数组元素 (arr[i]),如果(arr[i] * times + res > target)(arr[i - 1] * times + res < target)。就可以判断我们需要的答案就在([arr[i], arr[i - 1]])中。

​ 再对特殊情况考虑,对于第一个元素,搜索区间为([0, arr[0]])

代码(Python):

class Solution:
    def findBestValue(self, arr: List[int], target: int) -> int:

        def binary_search(left: int, right: int) -> int:
            """
            二分法,获得left,right中乘以times的积的差值最接近target的值
            """
            while left <= right:
                mid = (left + right) // 2
                mid_val = mid * times + res
                if mid_val == target:
                    return mid
                if mid_val < target:
                    left = mid + 1
                if mid_val > target:
                    right = mid - 1
            if abs(left * times + res - target) < abs(right * times + res - target):
                return left
            else:
                return right

        ans = 0
        arr.sort()
        if sum(arr) <= target:
            return arr[-1]
        n = len(arr)
        i = 0
        times = n
        res = 0
        # 当arr[i] * n > target and arr[i - 1] * n < target
        # 设置查找区间(arr[i - 1], arr[i])
        while arr[i] * times + res < target:
            res += arr[i]
            i += 1
            times -= 1

        if arr[i] * times + res == target:
            return arr[i]

        if arr[i] * times + res > target:
            if i == 0:
                ans = binary_search(0, arr[0])
            else:
                ans = binary_search(arr[i - 1], arr[i])
        return ans
原文地址:https://www.cnblogs.com/enmac/p/13127807.html