【力扣roadmap】2439. 最小化数组中的最大值

44 阅读2分钟

题目描述

  • 竞赛积分1965
  • 题号2439

思路

题眼是“最大值最小”,可以知道题目需要使用二分来做。 因此该问题的关键在于,你如何判断当前的候选答案是否是合法的,即check函数的编写。

我们以“流式”的思想,从最开始的元素x向后枚举,同时维护一个变量s(记账),最终要求债务不大于0即可。那么何为“账”?

我们举两个例子:

  • 对于序列1 2 4 6 10来讲,如果我们想判断“这个序列操作后,最小的最大值为7是否合法”,该怎么高效判断?(注意,我只是演示判断7是否合法,并不是说7就是这个样例的答案)首先让1与7比较,记账-6;然后2与7比较,记账为-6-5;然后4和7比较,记账为-6-5-3;然后6和7比较,记账为-6-5-3-1;最后10与7比较,记账-6-5-3-1+3 = -12 。 所以我们判断我们似乎有手段达到“最小的最大值为7”的目的。那么-12的意义是什么?他的意义就是“让所有元素变成7,我们还需要12才可以”。欠12没什么大问题,我们只需要保证序列有一个元素为7且这个元素是当前序列最大即可。
  • 对于序列10 1来讲,如果我们想判断“这个序列操作后,最小的最大值为6是否合法”,怎么判断?首先让10和6进行比较,发现记账为4,这就不对了。因为这个4我们没有办法移动到其他元素上,使得10变成6(因为10前面没有别的元素了)。所以直接返回False,判断6为非法。

代码

class Solution:
    def minimizeArrayValue(self, nums: List[int]) -> int:
        def check(ele) :
            s = 0 
            for x in nums :
                if (x - ele) > abs(s) :
                    return False 
                else :
                    s += x - ele 
            return s <= 0  
        l , r = 0 , max(nums) 
        while l < r :
            mid = l + (r - l ) // 2 
            # check mid 
            if check(mid) : # valid
                r = mid 
            else :
                l = mid + 1 
        return l