从一个数组中找出最接近目标_LeetCode每日一题 | 转变数组后最接近目标值的数组和...

题目来源:LC1300

ee381c1fd37a85ac55e0071e1bf60006.png

这道题目是一道比较经典的二分查找题。

我们注意到,当value越大时,数组之和越大,当value越小时,数组之和越小。因此,我们可以利用数组之和是value的单调递增函数这个性质来进行二分查找。

最大的可能value值是max(arr),因为在那之后继续增加value并不会改变数组里的元素值,从而无法改变数组之和。

最小的可能value值是target/n-1,这里n是数组的长度。value继续减小只会让数组之和与target渐行渐远。

因此,我们只需在这两个值之间进行二分查找即可。

def findBestValue(self, arr: List[int], target: int) -> int:    # 计算value为x时,数组之和    def getsum(x):        res = 0        for val in arr:            res = res + min(val, x)        return res    # 初始化    n = len(arr)    l = target // n - 1    r = max(arr)        # 二分查找    while l < r - 1:        mid = (l + r)//2        sum_arr = getsum(mid)        if sum_arr == target:            return mid        if sum_arr < target:            l = mid        else:            r = mid        if abs(getsum(l) - target) > abs(getsum(r) - target):        return r    return l

复杂度分析:

  • 时间上:外层二分查找最多需要log(max(arr))次循环,内层getsum函数需要最多n次循环。由于max(arr)最大不会超过10^5,因此 log(max(arr)) < 17 可以看做是一个常数。时间复杂度为O(n)。
  • 空间上:除去输入数组,我们只用了常数个变量,因此空间复杂度为O(1)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值