Given an array nums
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.
Example 1:
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.
Example 2:
Input: nums = [1,2,3,4,5], m = 2 Output: 9
Example 3:
Input: nums = [1,4,4], m = 3 Output: 4
Constraints:
1 <= nums.length <= 1000
0 <= nums[i] <= 106
1 <= m <= min(50, nums.length)
分割数组的最大值。
给定一个非负整数数组 nums 和一个整数 m ,你需要将这个数组分成 m 个非空的连续子数组。
设计一个算法使得这 m 个子数组各自和的最大值最小。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/split-array-largest-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这道题我给出一个比较好理解的二分法。这道题也有动态规划的做法,以后有机会再补充。
我第一次做这道题的时候觉得题意有点绕,这里重新解释一下。这道题是要你将数组分割成 M 个部分,分割之后每个子数组都是有一个各自的数组合的,所以一共会得到 M 个数组合。你要做的是找到一个分割方式使得这 M 个数组合中的最大值尽可能小。
这道题的二分法找的就是到底这个子数组的合是多少才比较合适。既然是查找就得有范围,这里查找的下界是数组里的最大值max,因为题目中给的 M 是有可能等于 input 数组长度的,也就是每个元素组成一个子数组;查找的上界是整个数组的前缀和,因为题目中给的 M 是有可能等于 1 的,也就是不分割这个数组。我这里用了一个helper函数去判断 mid 是否合适,其他的参见代码注释。
时间O(nlogn)
空间O(1)
Java实现
1 class Solution { 2 public int splitArray(int[] nums, int m) { 3 int max = 0; 4 long sum = 0; 5 for (int num : nums) { 6 max = Math.max(max, num); 7 sum += num; 8 } 9 10 // corner case 11 if (m == 1) { 12 return (int) sum; 13 } 14 15 // normal case 16 long left = max; 17 long right = sum; 18 while (left <= right) { 19 long mid = left + (right - left) / 2; 20 if (helper(nums, m, mid)) { 21 right = mid - 1; 22 } else { 23 left = mid + 1; 24 } 25 } 26 return (int) left; 27 } 28 29 private boolean helper(int[] nums, int m, long mid) { 30 // count记录目前分割了的子数组的个数 31 int count = 1; 32 long sum = 0; 33 for (int num : nums) { 34 sum += num; 35 // 如果子数组的和超过了设定的mid,那么就分割一块,count++ 36 // 并且要把当前的这个num计算到下一个子数组里 37 if (sum > mid) { 38 sum = num; 39 count++; 40 } 41 42 // 如果分割了超过M份,就退出 43 if (count > m) { 44 return false; 45 } 46 } 47 return true; 48 } 49 }