题目描述
竞赛积分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