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:
If n is the length of array, assume the following constraints are satisfied:

  • 1 ≤ n ≤ 1000
  • 1 ≤ m ≤ min(50, n)

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部分,假设有n种划分,假设max[i]为第i中情况能取到的最大值,求Math.min(max[0], max[1], ... max[i], ... , max[n-1])。

思路一:暴力求解,将取得各种划分情况,依次求解,但会TLE,程序如下所示:

class Solution {
    private int max = Integer.MAX_VALUE;
    public int splitArray(int[] nums, int m) {
        int[] parts = new int[m+1];
        backTracing(nums, 0, m, parts);
        return max;
    }
    public void backTracing(int[] nums, int begin, int m, int[] parts){
        if (begin > nums.length || m < 0){
            return;
        }
        if (m == 0){
            if (begin < nums.length){
                return;
            }
            int cur = 0;
            for (int val : parts){
                cur = Math.max(cur, val);
            }
            max = Math.min(max, cur);
            return;
        }
        for (int i = begin; i < nums.length; ++ i){
            parts[m] += nums[i];
            if (parts[m] > max){
                break;
            }
            backTracing(nums, i + 1, m - 1, parts);
        }
        parts[m] = 0;
    }
}

思路二:二分查找,通过二分查找算法直接查找目标值。

假设max为nums数组的最大值,sum为nums数组所有元素之和,可知,所求的各个情况最大值中的最小值(有点绕?但确实是这样)介于max和sum之间(含边界)。

class Solution {
    public int splitArray(int[] nums, int m) {
        int left = 0, right = 0;
        for (int val : nums){
            left = Math.max(left, val);
            right += val;
        }
        int mid = 0;
        while (left <= right){
            mid = left + ((right - left) >> 1);
            if (contains(nums, mid, m)){
                right = mid - 1;
            }
            else {
                left = mid + 1;
            }
        }
        return left;
    }
    
    public boolean contains(int[] nums, int target, int m){
        int total = 0, cnt = 0;
        for (int val : nums){
            total += val;
            if (total > target){
                total = val;
                cnt ++;
                if (cnt > m - 1){
                    return false;
                }
            }
        }
        return true;
    }
}
本题已经说明数组元素为非负数,因此思路二可行;如果含负数,思路二不行,思路一仍然可行,因此思路一更具有通用性。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值