问题:
给出一个数组,将其分成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 };