You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改最小化最大子数组和算法以实现最大化最小子数组和?

问题描述

给定整数数组nums和整数k,需将nums分割为k个非空连续子数组,使得所有子数组中的最小和尽可能大,返回该最大化后的最小和。

示例:

  • 输入:nums = [7,2,5,10,8],k = 2
  • 输出:14

现有一个求解最小化最大子数组和的算法(代码如下),请问如何修改该算法以实现上述需求?

class Solution {
    int[] nums;
    public int splitArray(int[] nums, int m) {
        this.nums = nums;
        int low = 0, high = 0, min = Integer.MAX_VALUE;
        for(int i=0;i<nums.length;i++){
            low = Math.max(low, nums[i]);
            high += nums[i];
        }
        while(low <= high) {
            int mid = (low + high) / 2;
            if(required_no_of_chunks(mid, m)){
               min = Math.min(min, mid);
               high = mid - 1;
            }
            else low = mid + 1;
        }
        return min;
    }
    
    private boolean required_no_of_chunks(int mid, int m){
        int chunks = 0, i=0;
        while(i < nums.length){
            int val = 0;
            while(i < nums.length && nums[i] + val <= mid) val += nums[i++];
            chunks++;
        }
        return chunks <= m;
    }
}

修改思路与实现

原算法通过二分查找求解「最小化的最大子数组和」,核心是判断当子数组最大和为mid时,所需分割数是否≤m。要改为求解「最大化的最小子数组和」,需从以下几点调整:

1. 二分边界重置

  • low:设为数组中的最小值(子数组至少包含一个元素,最小和的最大值不会小于单个元素的最小值);
  • high:设为数组的总和(当k=1时,唯一子数组的和就是总和,即最小和的最大值)。

2. 二分搜索方向调整

原算法是找最小的可行mid,因此找到可行值后会尝试更小的mid;现在我们要找最大的可行mid,找到可行值后需尝试更大的mid,不可行时再缩小范围。

3. 判断函数改写

将原判断「子数组最大和为mid时的分割数」改为判断「能分割出多少个和≥mid的子数组」,若数量≥k,说明当前mid可行(可通过合并子数组得到恰好k个,且每个子数组和仍≥mid)。

修改后的完整代码

class Solution {
    int[] nums;
    public int splitArrayMaxMinSum(int[] nums, int k) {
        this.nums = nums;
        int low = Integer.MAX_VALUE;
        int high = 0;
        int maxResult = 0;
        
        // 初始化二分边界
        for (int num : nums) {
            low = Math.min(low, num);
            high += num;
        }
        
        while (low <= high) {
            // 避免整数溢出的写法
            int mid = low + (high - low) / 2;
            if (isValid(mid, k)) {
                // 当前mid可行,尝试更大的值
                maxResult = mid;
                low = mid + 1;
            } else {
                // 当前mid不可行,尝试更小的值
                high = mid - 1;
            }
        }
        return maxResult;
    }
    
    private boolean isValid(int mid, int k) {
        int count = 0;
        int currentSum = 0;
        for (int num : nums) {
            currentSum += num;
            // 累加和≥mid时,完成一个符合要求的子数组
            if (currentSum >= mid) {
                count++;
                currentSum = 0;
            }
        }
        // 若能分割出≥k个符合要求的子数组,说明mid可行
        return count >= k;
    }
}

内容的提问来源于stack exchange,提问作者learner26

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 21:39:53