1. 【问题描述】 最大子数组
2. 【思路】 参考算法导论
采用分而治之的策略。假设数组nums共有N个元素,下标范围 0—N-1,令过程maxBE(nums,beg,end)可以返回nums的下标范围 beg—end的子数组的最大子数组和,即nums[beg,...,end]的最大子数组和,下面对maxBE过程进行分析:
(1). beg==end 则直接返回nums[beg];
(2). beg!=end 则令mid=beg+(end-beg)/2,将数组nums[beg,...,end]拆分为两个子数组nums_left[beg,...,mid]和nums_right[mid+1,...,end],数组nums[beg,...,end]的最大子数组来自以下三种情况中的一种:
2.1 完全来自 nums_left[beg,...,mid];
2.2 完全来自 nums_right[mid+1,...,end];
2.3 由nums_left的尾部一部分和nums_right的头部一部分组成;
2.1和2.2所示的情形是原问题的规模更小的子问题,可以递归调用过程maxBE求解。下面说一下2.3所示情形的解决方法。在这种情况下,最大子数组一定包含原数组nums的元素nums[mid]和nums[mid+1],从下标mid处往前累加数组元素,找到此过程中的累加和的最大值,设为sum_left,从数组下标mid+1往后累加数组元素,找到此过程中累加和的最大值,设为sum_right,则2.3所示情形的最大子数组和是sum_left+sum_right。最终的返回值是2.1、2.2和2.3三种情况中的最大值.
下面以一个小例子分析一下。假设包含三个元素的数组[-2,2,3],下面按行列出分拆过程:
[-2,2,3] [-2,2] [3]
[-2,2] [-2] [2]
3.【代码】
class Solution {
public:
/**
* @param nums: A list of integers
* @return: A integer indicate the sum of max subarray
*/
int maxBE(vector<int> &nums,int beg,int end) {
if(beg==end) {
return nums[beg];
}
int mid=beg+(end-beg)/2;
int i=mid-1,left=nums[mid],ls=left;
while(i>=beg) {
ls+=nums[i];
left=left>=ls?left:ls;
i--;
}
int j=mid+2,right=nums[mid+1],rs=right;
while(j<=end) {
rs+=nums[j];
right=right>=rs?right:rs;
j++;
}
int mid_sum=left+right,left_sum=maxBE(nums,beg,mid),right_sum=maxBE(nums,mid+1,end);
int sum=left_sum>=right_sum?left_sum:right_sum;
return sum>=mid_sum?sum:mid_sum;
}
int maxSubArray(vector<int> nums) {
// write your code here
if(nums.empty()) {
return 0;
}
return maxBE(nums,0,nums.size()-1);
}
};