问题:
给出一个数组,将其分成m段,求出分段方法中,要求最小化这些连续子数组的最大和。
思路:
为了最小化这些连续子数组的最大和,必然每一段的和都是接近的。我们这里引入一种二分查找的思想。
首先,在不考虑分多少段的情况下,子数组的和最小值,肯定是子数组只包含数组中最小的值,我们假设这个数为min_sum。
而在不考虑分多少段的情况下,子数组的和最大值,肯定是包含数组中的所有数的和,我们假设这个数为max_sum。
那么,我们要找的最小的连续数组最大和,则肯定在[min_sum, max_sum]这个区间内。
我们迭代地找出这个区间的中值mid,然后顺序地检索整个数组,看数组根据这个mid值能够分多少段
如果段数多于m段,则证明这个mid太小了,我们更新min_sum为mid+1
如果段数少于m段,则证明这个mid太大了,不能满足分段要求。我们更新max_sum为mid-1
最后当min_sum第一次大于max_sum的时候,则是我们要找的最小的连续子数组最大和了。
代码:
1 class Solution {
2 public:
3 int splitArray(vector<int>& nums, int m) {
4 long min_sum = 0, max_sum = 0;
5 for (int i = 0; i < nums.size(); i++) {
6 if (nums[i] > min_sum)
7 min_sum = nums[i];
8 max_sum += nums[i];
9 }
10 while (min_sum <= max_sum) {
11 long mid = (min_sum + max_sum) / 2;
12 int split_arrays = 1;
13 long current_sum = 0;
14 for (int i = 0; i < nums.size(); i++) {
15 if (current_sum + nums[i] <= mid) {
16 current_sum += nums[i];
17 }
18 else {
19 current_sum = nums[i];
20 split_arrays++;
21 }
22 }
23 if (split_arrays <= m)
24 max_sum = mid - 1;
25 else
26 min_sum = mid + 1;
27 }
28 return min_sum;
29 }
30 };
知识兔