zoukankan      html  css  js  c++  java
  • 【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
    
  • 相关阅读:
    HDU 6464 /// 权值线段树
    HDU 6468 /// DFS
    HDU 6469 /// 二分
    HDU 6470 /// 矩阵快速幂
    USACO 2014 US Open Odometer /// 数位DP
    hdu5988(费用流,对数相乘做加法)
    对AC自动机+DP题的一些汇总与一丝总结 (2)
    对AC自动机+DP题的一些汇总与一丝总结 (1)
    POJ 1625 Censored ( Trie图 && DP && 高精度 )
    HDU 2243 ( Trie图 矩阵构造幂和 )
  • 原文地址:https://www.cnblogs.com/enmac/p/13127807.html
Copyright © 2011-2022 走看看