Split Array Largest Sum LT410

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.

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.

Note:
If n is the length of array, assume the following constraints are satisfied:

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

Idea 1. dynmaic programming, similar to Capacity To Ship Packages Within D Days LT1011

dp(i)(m) = min(i <= k <= n - m) max(prefixSum(k+1) - prefixSum(i), dp(k+1)(m-1))

Note: prefixSum integer overflow, pls use long.

Time complexity: O(mn^2)

Space complexity: O(n)

 1 class Solution {
 2     public int splitArray(int[] nums, int m) {
 3         int n = nums.length;
 4        
 5         long[] prefixSum = new long[n+1];
 6         for(int i = 1; i <= n; ++i) {
 7             prefixSum[i] = prefixSum[i-1] + nums[i-1];
 8         }
 9         
10         long[] dp = new long[n];
11         for(int i = 0; i < n; ++i) {
12             dp[i] = prefixSum[n] - prefixSum[i];
13         }
14         
15         for(int split = 2; split <= m; ++split) {
16             for(int i = 0; i <= n -split; ++i) {
17                 for(int k = i; k <= n - split; ++k) {
18                     long val = Math.max(prefixSum[k+1] - prefixSum[i], dp[k+1]);
19                     dp[i] = Math.min(dp[i], val);
20                     // if(val <= dp[i]) { //positive optimisation
21                     //     dp[i] = val;
22                     // }
23                     // else {
24                     //     break;
25                     // }
26                 }
27             }
28         }
29         
30         return (int)dp[0];
31     }
32 }

Idea 2. binary search

search space: min = max(max(nums), sum(nums)/m), max = sum(nums)

 1 class Solution {
 2     private int checkSplits(int[] nums, int load) {
 3         int splits = 1;
 4         int sum = 0;
 5         for(int num: nums) {
 6             if(sum + num > load) {
 7                 ++splits;
 8                 sum = num;
 9             }
10             else sum += num;
11         }
12         return splits;
13     }
14     public int splitArray(int[] nums, int m) {
15         int n = nums.length;
16        
17         long sum = 0;
18         int minSum = 0;
19         for(int num: nums) {
20             minSum = Math.max(minSum, num);
21             sum += num;
22         }
23         
24         int maxSum = (int)(sum);
25         minSum = Math.max(minSum, (int)(sum-1)/m + 1);
26         while(minSum < maxSum) {
27             int mid = minSum + (maxSum - minSum)/2;
28             int splits = checkSplits(nums, mid);
29             if(splits <= m) {
30                 maxSum = mid;
31             }
32             else {
33                 minSum = mid + 1;
34             }
35         }
36         return minSum;
37     }
38 }

猜你喜欢

转载自www.cnblogs.com/taste-it-own-it-love-it/p/10668329.html