LeetCode No.410 Split Array Largest Sum

Given an array which consists of non-negative integers and an integer m, you can split the array into m non-empty continuous subarrays. Write an algorithm to minimize the largest sum among these m subarrays.

Note:
Given m satisfies the following constraint: 1 ≤ m ≤ length(nums) ≤ 14,000.

Examples:

Input:
nums = [7,2,5,10,8]
m = 2

Output:
18

Explanation:
There are four ways to split nums into two subarrays.
The best way is to split it into [7,2,5] and [10,8],
where the largest sum among the two subarrays is only 18.
====================================================================================================================================

此题目的大意是:将给定数组切割成m份,求这m份中最大和的最小值(即求极大的极小问题)。

因为我们知道切割的方法,用二分+搜索求解就可以了。

所谓二分,就是确定结果的最大值maxerf和最小值miner,取两者的中间值mid。而搜索便是:判断mid是否符合条件,如果符合,则令miner=mid+1,同时记录下ans,否则,令maxer=mid-1,以此类推,当miner>maxer时结束。

方法不难,但是我们还要注意一些细节上的问题:

(1)nums = [1,2147483647] ,m = 1 时,计算maxer的时候会越界,而且计算繁杂,应单独处理

(2)nums = [1,2147483647] ,m = 2 时,计算maxer的时候会越界,得到的maxer为负数,这时候,要令maxer = 2147483647。

(3)在搜索的时候,当当前和temp==mid时,要判断此时是否为数组的结尾,再确定sum是否加1。

class Solution {
public:
    int splitArray(vector<int>& nums, int m) {
        int n = nums.size() ;
        if ( n == 0 )
            return 0 ;
        int miner = 0 , maxer = 0 ;
        for ( int i = 0 ; i < n ; i ++ )
        {
            maxer += nums[i] ;
            miner = max ( miner , nums[i] ) ;
        }
        if ( m == 1 )
            return maxer ;
        int ans = maxer ;
        if ( maxer < 0 )
            maxer = 2147483647 ;
        miner = max ( miner , maxer / m ) ;
        while ( miner <= maxer )
        {
            int mid = ( (unsigned int) miner + maxer ) / 2 , temp = 0 , sum = 1 ;
            for ( int i = 0 ; i < n ; i ++ )
            {
                temp += nums[i] ;
                if ( temp > mid )
                {
                    sum ++ ;
                    temp = nums[i] ;
                }
                else if ( temp == mid )
                {
                    if ( i != n - 1 )
                        sum ++ ;
                    temp = 0 ;
                }
            }
            if ( sum <= m )
            {
                ans = mid ;
                maxer = mid - 1 ;
            }
            else
                miner = mid + 1 ;
        }
        return ans ;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值