410. Split Array Largest Sum

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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: 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.

二分法:

public int splitArray(int[] nums, int m) {
        long sum = 0;
        int max = 0;
        for(int num: nums){
            max = Math.max(max, num);
            sum += num;
        }
        return (int)binarySearch(nums, m, sum, max);
    }
    //二分查找
    private long binarySearch(int[] nums, int m, long high, long low){
        long mid = 0;
        while(low < high){
            mid = (high + low)/2;
            //验证是否满足,也就是这么大的值有可能出现么
            if(valid(nums, m, mid)){
                high = mid;
            }else{
                low = mid + 1;
            }
        }
        return high;
    }

    /**
     * 验证这个值是否合法
     * */
    private boolean valid(int[] nums, int m, long max){
        int cur = 0;
        int count = 1;
        //是否有多余m个片段or区间,大于给定值的max的,如果有了,那么就不合法了,因为这样划分就不止m个,及max太小
        for(int num: nums){
            cur += num;
            if(cur > max){
                cur = num;
                count++;
                if(count > m){
                    return false;
                }
            }
        }
        return true;
}

动归: 最大, 最小, 不能排序, 而且是求区间和的改写, 先考虑用一维动归, dp[m]表示分为m组,  写不出状态转移方程. 并且, 这是最大值最小的问题, 先找最大, 再找最小, 所以用二维数组, 题中就是组数, 和第几个人是变量, 因此dp[m][n] 表示将n个人分为m组的结果值, 这样有了两层外循环, 看递推公式与两层外循环的关系:

dp[m][n] =  min (dp[m][n], Un-1 j = m - 1  max(dp[m - 1][j], sum[n] - sum[j]) (内循环多是最后一次分割点位置变化, 和前一次分割的关系 )

因为dp[m - 1][j] 不能直接得到, 所以需要 外循环 动归到dp[m][n], 其实想想也很简单, 只有外循环先建立起来了, 才有内循环的递推公式. 

一维状态方程常考虑: 要不要该点, 

二维状态方程常考虑: 分割点(与题目的值(sums[j] - sums[k]) 联系最紧密 , 当前分割的次数与前一次数有什么关系

subarray 和的问题常转化为 区间和的问题, (sums[j] - sums[k])

起点的初始化要正常, 中间点的初始化时为了比较(min, max) 等.------知道的初始化正常值, 不知道的初始化为对立值.

 

 

public int splitArray(int[] nums, int m) {
        int n = nums.length;
        int[][] dp = new int[m + 1][nums.length + 1];
     
        int[] sums = new int[n + 1];
        for (int i = 1; i <= n; ++i) {
            sums[i] = sums[i - 1] + nums[i - 1];
            
        }
        for (int i = 0; i <= m; ++i) {
            for (int j = 0; j <= n; ++j) {
                dp[i][j] = Integer.MAX_VALUE;
            }
        }
        dp[0][0] = 0;
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                for (int k = i - 1; k < j; ++k) {
                    int val = Math.max(dp[i - 1][k], sums[j] - sums[k]);
                    dp[i][j] = Math.min(dp[i][j], val);
                }
            }
        }
        return dp[m][n];
}

  

以上是关于410. Split Array Largest Sum的主要内容,如果未能解决你的问题,请参考以下文章

410. Split Array Largest Sum

410. Split Array Largest Sum

410. Split Array Largest Sum

Split Array Largest Sum LT410

Leetcode 410. Split Array Largest Sum

leetcode 410. Split Array Largest Sum