day124—二分查找—最小化数组中的最大值(LeetCode-2439)

题目描述

给你一个下标从 0 开始的数组 nums ,它含有 n 个非负整数。

每一步操作中,你需要:

  • 选择一个满足 1 <= i < n 的整数 i ,且 nums[i] > 0
  • nums[i] 减 1 。
  • nums[i - 1] 加 1 。

你可以对数组执行 任意 次上述操作,请你返回可以得到的 nums 数组中最大值 最小 为多少。

示例 1:

复制代码
输入:nums = [3,7,1,6]
输出:5
解释:
一串最优操作是:
1. 选择 i = 1 ,nums 变为 [4,6,1,6] 。
2. 选择 i = 3 ,nums 变为 [4,6,2,5] 。
3. 选择 i = 1 ,nums 变为 [5,5,2,5] 。
nums 中最大值为 5 。无法得到比 5 更小的最大值。
所以我们返回 5 。

示例 2:

复制代码
输入:nums = [10,1]
输出:10
解释:
最优解是不改动 nums ,10 是最大值,所以返回 10 。

提示:

  • n == nums.length
  • 2 <= n <= 105
  • 0 <= nums[i] <= 109

解决方案:

问题目标

给定一个数组,可以通过操作(将某个元素减1,同时将其左侧相邻元素加1)来调整数组,目标是最小化调整后数组的最大值

算法框架

1. 核心思想:二分查找答案

  • 我们不知道最小化的最大值是多少,但可以猜测一个值

  • 如果猜测值太小,无法通过操作使所有元素不超过它

  • 如果猜测值足够大,总能满足要求

  • 使用二分查找找到最小的满足条件的值

2. 二分查找部分

  • left 初始为 -1(确保答案比它大)

  • right 初始为数组最大值(这是肯定可行的上限)

  • 不断二分,检查中间值 mid 是否可行

  • 最终 right 就是最小可行值

3. 关键:check 函数(贪心验证)

检查给定限制 limit 是否可行:

  • 右向左遍历数组(因为只能向左传递数值)

  • 维护 dx 变量:表示需要向左传递的"超额"部分

  • 对于每个位置 i,计算当前值加上传递来的值

  • 如果超过 limit,超额部分继续向左传递

  • 最后检查第一个元素加上传递来的值是否不超过 limit

直观例子

假设 nums = [3, 7, 1, 6]limit = 5

  • 从右向左处理:

    • i=3: 6 ≤ 5? false,超额1传递给左边

    • i=2: 1 + 1 = 2 ≤ 5,无超额

    • i=1: 7 ≤ 5? false,超额2传递给左边

    • i=0: 3 + 2 = 5 ≤ 5,可行

算法特点

  • 时间复杂度:O(n log M),其中M是数组最大值

  • 空间复杂度:O(1)

  • 利用了单调性:如果limit可行,那么更大的limit也一定可行

  • 贪心策略最优:从右向左尽量传递超额值是最有效的

函数源码:

cpp 复制代码
class Solution {
public:
    bool check(vector<int>nums,int limit){
        long long dx=0;
        for(int i=nums.size()-1;i>0;i--){
            long long newNum=nums[i]+dx;
            dx=max(newNum-limit,0LL);
        }

        return nums[0]+dx<=limit;
    }

    int minimizeArrayValue(vector<int>& nums) {
        int max=*max_element(nums.begin(),nums.end());
        int left=-1;
        int right=max;

        while(left+1<right){
            int mid=(left+right)/2;
            if(check(nums,mid)){
                right=mid;
            }else{
                left=mid;
            }

        }
        return right;
    }
};
相关推荐
predawnlove2 小时前
【NCCL】4 AllGather-PAT算法
算法·gpu·nccl
驱动探索者2 小时前
[缩略语大全]之[内存管理]篇
java·网络·算法·内存管理
·云扬·2 小时前
MySQL Join关联查询:从算法原理到实战优化
数据库·mysql·算法
bbq粉刷匠2 小时前
二叉树中两个指定节点的最近公共祖先
java·算法
Alsn863 小时前
29.Java中常见加解密算法的基本实现
java·开发语言·算法
1001101_QIA3 小时前
OpenMP学习笔记
算法
Coovally AI模型快速验证3 小时前
YOLO11算法深度解析:四大工业场景实战,开源数据集助力AI质检落地
人工智能·神经网络·算法·计算机视觉·无人机
(❁´◡`❁)Jimmy(❁´◡`❁)3 小时前
【算法】 二分图理论知识和判断方法
c++·算法
徐子童3 小时前
优选算法---哈希表
数据结构·算法·哈希表