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;
    }
};
相关推荐
阳明山水4 小时前
校准分位数驱动智能库存决策
人工智能·深度学习·算法·机器学习·架构
别动我齐刘海5 小时前
ROS2 Jazzy + C++ 实战路线——进阶学习3
c++·人工智能·vscode·python·算法·机器学习·机器人
zhangfeng11335 小时前
《从“人工适配“到“智能生成“:KernelSwift 跨国产芯片算子迁移全栈方案解读》 —— 强调范式跃迁和跨硬件属性,适合偏架构分析的写法
人工智能·算法·华为·ai编程·npu
0+1115 小时前
算法 --滑动窗口
c++·算法·leetcode
reikocao6 小时前
大场景下 Hessian 特征值放大与退化检测
算法
hetao17338376 小时前
2026-09-18 hetao1733837 的刷题记录
c++·算法
wuyk5556 小时前
21.计数排序:不用比较的“空间换时间”排序算法
python·算法·排序算法
Rabitebla6 小时前
【Linux系统编程】 指令(二):一条路径是怎么定位到文件的
linux·c++·笔记·学习·算法
库玛西7 小时前
数据结构与算法之美:树、森林与二叉树全解析
c语言·数据结构·笔记·考研·算法·学习方法
木井巳7 小时前
【记忆化搜索】最长递增子序列
java·算法·leetcode·深度优先·剪枝·推荐算法