【leetcode】No.410:split-array-largest-sum

题目描述

给定一个非负整数数组和一个整数m,你需要将这个数组分成m个非空的连续子数组。设计一个算法使得这m个子数组各自和的最大值最小。

注意:

数组长度n满足以下条件:

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

输入:

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

输出:

18

解释:

一共有四种方法将nums分割为2个子数组。
其中最好的方式是将其分为[7,2,5][10,8]
因为此时这两个子数组各自的和的最大值为18,在所有情况中最小。

思路:

dp[i][j]表示前i个数字分成j段时各自和的最大值最小为dp[i][j],很容易想到初始情况dp[i][1]nums[1]+nums[2]+....+nums[i]
更为一般的情况,想求dp[i][j],可以考虑将使用k将前i个数字分成0~kk~i两部分,k~i为最后一段,这时各段和最大值则为dp[k][j-1]k~i这段和中较大者。k~i这段的和为dp[i][1]-dp[k][1]。遍历k0i-1,从中选择最小的一个作为dp[i][j]的值。最终返回dp[len-1][m]就是答案。

代码:

class Solution {
    public int splitArray(int[] nums, int m) {
        int len = nums.length;
        int[][] dp = new int[len][m+1];
        dp[0][1] = nums[0];
        for (int i=1; i<len; i++){
            dp[i][1] = dp[i-1][1] + nums[i];
        }
        for (int i=0; i<len; i++){
            for (int j=2; j<=m; j++){
                int minSumMax = Integer.MAX_VALUE;
                for (int k=0; k<i; k++){
                    minSumMax = Math.min(minSumMax , Math.max(dp[k][j-1], dp[i][1]-dp[k][1]));
                }
                dp[i][j] = minSumMax ;
            }
        }
        return dp[len-1][m];
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 3,429评论 0 2
  • LeetCode Dynamic Programming DP 九章DP班归纳: 坐标型DP:保存的是坐标的状态;...
    Deepin_阅读 630评论 0 1
  • 转载自:https://egoistk.github.io/2016/09/10/Java%E6%8E%92%E5...
    chad_it阅读 1,012评论 0 18
  • (欢迎转载,但请注明出处并附带链接)算法好久没复习了,今天看见一妹子在办公室刷Leetcode,顿时我也来了兴趣,...
    Nick_Zuo阅读 700评论 0 3
  • 今天同病室的老先生终于做手术了,放了几个支架,主治医生说了后期要康复训练,但不保证没有后遗症,手术是为了防止下次...
    娟_07ba阅读 412评论 0 1