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 }
原文地址:https://www.cnblogs.com/taste-it-own-it-love-it/p/10668329.html
时间: 2024-10-24 12:29:04