LeetCode 410. Split Array Largest Sum

16 篇文章 0 订阅

题目:给出一个由非负整数组成的数组和整数m,把该数组切分成m个非空连续子数组,并最小化m个子数组总值最大值。

注意:1 ≤ n ≤ 1000,1 ≤ m ≤ min(50, n) 其中n为数组长度。

例子:

输入:nums = [7,2,5,10,8]
           m = 2
输出:18

解题思路:显然,无论怎么切分数组,各子数组的总值中的最大值不小于数组中最大的元素。那么就有一个输出值的下界,而上届就是数组中各元素之和,即m=1时。用二分法更新上下界,最后找到输出值。说到二分法,那么就会出现middle值,每次如何确定是将上界upper更新为middle呢还是将下界lower更新为middle+1呢?

当以middle值为界限切分数组时,即每个子数组总值小于等于middle,需要m*次切割才能完成对数组的切割,此时将m*与输入的m比较,若m*>m,则说明middle值过小,需要更新下界来增加middle值,从而增加子数组的容量减少切分次数;若m*<=m,则说明子数组的容量足够,可以在m次切割内对数组的切割,则可以尝试使用更小的middle值,此时更新上界。

代码如下:

class Solution {
public:
    int splitArray(vector<int>& nums, int m) {
        int maxVal=0;
        long int sum=0;
        for(int i = 0; i < nums.size(); ++i){
            sum += nums[i];
            if(maxVal < nums[i]) maxVal = nums[i];
        }
        if(m==1) return sum;
        return binsearch(nums,m,maxVal,sum);
    }
    int binsearch(vector<int>& nums, int m, int maxVal, long int sum){
        int lower = maxVal;
        long int upper = sum;
        while(lower < upper){
            long int middle = lower + (upper - lower)/2;
            if(passIt(nums,m,middle)) {
                upper = middle;
            }
            else {
                lower = middle + 1;
            }
        }
        return upper;
    }
    bool passIt(vector<int>& nums, int m, long int middle){
        int num = 1,sub = 0;
        for(int i = 0; i < nums.size(); ++i){
            if(sub + nums[i] <= middle){
                sub += nums[i];
            }
            else{
                num++;
                sub = nums[i];
                if(num > m) return false;
            }
        }
        return true;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值