Minimize Maximum of Array

Minimize Maximum of Array

You are given a 0-indexed array nums comprising of n non-negative integers.

In one operation, you must:

  • Choose an integer i such that 1i<n and nums[i]>0.
  • Decrease nums[i] by 1.
  • Increase nums[i1] by 1.

Return the minimum possible value of the maximum integer of nums after performing any number of operations.

Example 1:

复制代码
Input: nums = [3,7,1,6]
Output: 5
Explanation:
One set of optimal operations is as follows:
1. Choose i = 1, and nums becomes [4,6,1,6].
2. Choose i = 3, and nums becomes [4,6,2,5].
3. Choose i = 1, and nums becomes [5,5,2,5].
The maximum integer of nums is 5. It can be shown that the maximum number cannot be less than 5.
Therefore, we return 5.
复制代码

Example 2:

Input: nums = [10,1]
Output: 10
Explanation:
It is optimal to leave nums as is, and since 10 is the maximum value, we return 10.

Constraints:

n==nums.length
2n105
0nums[i]109

 

解题思路

  比赛的时候一直想着怎么用贪心去做出来,结果还是没想到。这题的话可以用二分,像最大化最小值最小化最大值这类问题应该先想想能不能用二分来做。

  假设最小的最大值,也就是答案为ans,那么根据假设小于ans的肯定不满足条件,因为无法构造出元素最大值小于的ans的序列,而大于等于ans是满足条件的,我们可以构造出元素最大值大于等于ans的序列。因此答案具有二段性,可以用二分。当二分出mid后,从后往前遍历数组(因为改变当前元素会对前面的元素产生变化,而对后面的元素不产生变化),如果nums[i]>mid,那么就把num[i]变成mid,同时nums[i1]要加上midnums[i],这样就保证了区间[1,n1]最内的数的最大值不超过mid,最后再判断nums[0]是否不超过mid

  AC代码如下:

复制代码
 1 class Solution {
 2 public:
 3     bool check(vector<int> &nums, int mid) {
 4         long long t = nums.back();
 5         for (int i = nums.size() - 1; i; i--) {
 6             if (t > mid) t = t - mid + nums[i - 1];
 7             else t = nums[i - 1];
 8         }
 9         return t <= mid;
10     }
11     
12     int minimizeArrayValue(vector<int>& nums) {
13         int l = 0, r = *max_element(nums.begin(), nums.end());
14         while (l < r) {
15             int mid = l + r >> 1;
16             if (check(nums, mid)) r = mid;
17             else l = mid + 1;
18         }
19         return l;
20     }
21 };
复制代码

  当然,也是由贪心解法的。反正我遇到贪心或者思维题基本都写不出来的。

  假设当前序列的最小的最大值为maxv,那么次数再往序列后面添加一个元素。如果这个元素小于等于maxv,那么只要我们对这个新元素进行操作,只可能会增加前面元素的最大值,而不会使得最大值变小。如果这个元素大于maxv,那么可以把多出来的情况均摊分给前面的元素,那么最后最小的最大值为a0++aii+1,当然这是最理想的情况,实际上不一定可以做到均分,比如序列 4,7,2,2,9 ,4+7+2+2+95=5,实际上这个序列的最小的最大值为6。因此最小的最大值要a0++aii+1

  因此我们可以从前往后遍历每一个元素,如果nums[i]maxv,那么不做处理。如果nums[i]>maxv,那么更新maxv=max(maxv,a0++aii+1)(如果是nums[i]maxv也可以做这个操作,因为得到的均值一定是比maxv要小的,不影响答案)。注意这里不可以直接赋值maxv=a0++aii+1,因为前面我们说过均值是最小下限,因此最小的最大值是所有最小下限的最大值。

  AC代码如下:

复制代码
class Solution {
public:
    int minimizeArrayValue(vector<int>& nums) {
        long long maxv = nums[0], sum = nums[0];
        for (int i = 1; i < nums.size(); i++) {
            sum += nums[i];
            maxv = max(maxv, (sum + i) / (i + 1));
        }
        return maxv;
    }
};
复制代码

 

参考资料

  两种做法:二分答案 / 分类讨论:https://leetcode.cn/problems/minimize-maximum-of-array/solution/liang-chong-zuo-fa-er-fen-da-an-fen-lei-qhee6/

posted @   onlyblues  阅读(109)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示