410. Split Array Largest Sum

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.


解法: 求一些最大值的最小值或一些最小值的最大值,是DP的关键词,所以想到DP。这道题的关键是想到让最后的元素分为一组,之前的元素分成 j - 1 组。 

           0  1  2  3 
    0      0  0  0  0
    1  7   0  7 ++ ++
    2  2   0  9   
    3  5   0 14
    4 10   0 24
    
    1. dp[i][j]: first i elements, split into j groups, minimal of larget sum among the groups.
    2. init: dp[i][j]: ++ 
             dp[i][1]: first i elements 1 group, sum. 
             dp[i][0]: 0
             dp[0][i]: 0
    3. dp[i][j]: 
    e.g.
    dp[4][3]: 7 2 5 10 into 3 groups的答案
    即最后的元素分为一组,之前的元素分成2组的所有答案的最小 - min((i),(ii),(iii))
    i) 7 | 2 5 10    max(dp[1][2], sum(2,5,10)) (dp[1][2]: invalid, continue)
    ii) 7 2 | 5 10    max(dp[2][2], sum(5,10))
    iii) 7 2  5 | 10   max(dp[3][2], sum(10))
    
    formula: dp[i][j] = min{max(dp[k][j - 1], sum(k+1,i))} for k = [1,i-1]

 

 1 public int splitArray(int[] nums, int m) {
 2         int[][] dp = new int[nums.length + 1][m + 1];
 3         for (int i = 0; i < dp.length; i++) {
 4             Arrays.fill(dp[i], Integer.MAX_VALUE);
 5         }
 6         // init
 7         for (int i = 0; i < dp.length; i++) {
 8             dp[i][0] = 0;
 9         }
10         for (int i = 0; i < dp[0].length; i++) {
11             dp[0][i] = 0;
12         }
13         for (int i = 1; i < dp.length; i++) {
14             dp[i][1] = dp[i - 1][1] + nums[i - 1];
15         }
16         
17         for (int i = 2; i < dp.length; i++) {
18             for (int j = 2; j < dp[0].length; j++) {
19                 int ans = Integer.MAX_VALUE;
20                 int totalSum = dp[i][1]; // for calculating sum(k+1,i). totalSum =  sum[0, i]
21                 int cumSum = 0; // for calculating sum(k+1,i). cumSum of first k.
23 for (int k = 1; k <= i - 1; k++) { 24 cumSum += nums[k - 1]; // outside, no matter what, add curSum 25 if (dp[k][j - 1] != Integer.MAX_VALUE) { 26 ans = Math.min(ans, Math.max(dp[k][j - 1], totalSum - cumSum)); 27 } 28 } 29 30 dp[i][j] = ans; 31 32 } 33 } 34 return dp[dp.length - 1][dp[0].length - 1]; 35 }

 

posted @ 2019-04-13 00:32  衣领子  阅读(170)  评论(0编辑  收藏  举报