利用分治法求解最大连续子数组问题:
1、将数组均分两段,递归分治。
2、对于每层分治,最大子数组要么出现在左段或者右段,要么出现在包含中点的连续数组中,从中点出发向左右遍历求最大数组。
3、每层最大子数组为左段最大子数组,右段最大子数组及包含中点的最大子数组的最大值。
代码如下:
#include <iostream>
#include <cstdlib>
#include <limits>
using namespace std;
/*
* name : find max subarray
* author : sangoly
* O(nlgn)
* date : 2014/4/18
*/
class MaxSubArrayInfo{
public:
MaxSubArrayInfo(int leftIndex, int rightIndex, int sum) : maxLeftIndex(leftIndex),
maxRightIndex(rightIndex), maxSum(sum) {}
int maxLeftIndex;
int maxRightIndex;
int maxSum;
bool operator>=(const MaxSubArrayInfo& info) {
return this->maxSum >= info.maxSum;
}
bool operator==(const MaxSubArrayInfo& info) {
return this->maxSum = info.maxSum;
}
bool operator<(const MaxSubArrayInfo& info) {
return !((*this) >= info);
}
};
MaxSubArrayInfo& findMaxCrossingSubArray(int array[], int left, int middle, int right)
{
int min = numeric_limits<int>::min();
int leftMaxSum = min;
int leftSum = 0;
int leftMaxIndex = middle;
for (int i=middle; i>=left; i--) {
leftSum += array[i];
if (leftSum > leftMaxSum) {
leftMaxSum = leftSum;
leftMaxIndex = i;
}
}
int rightMaxSum = min;
int rightSum = 0;
int rightMaxIndex = middle + 1;
for (int i=middle+1; i<=right; i++) {
rightSum += array[i];
if (rightSum >= rightMaxSum) {
rightMaxSum = rightSum;
rightMaxIndex = i;
}
}
MaxSubArrayInfo *ret = new MaxSubArrayInfo(leftMaxIndex, rightMaxIndex, leftMaxSum+rightMaxSum);
return *ret;
}
MaxSubArrayInfo& findMaxSubArray(int array[], int left, int right)
{
int leftMaxIndex, rightMaxIndex, sumMax;
int middleIndex = (left + right) / 2;
if (left == right) {
leftMaxIndex = left;
rightMaxIndex = right;
sumMax = array[left];
MaxSubArrayInfo *ret = new MaxSubArrayInfo(leftMaxIndex, rightMaxIndex, sumMax);
return *ret;
} else {
MaxSubArrayInfo leftMaxInfo = findMaxSubArray(array, left, middleIndex);
MaxSubArrayInfo rightMaxInfo = findMaxSubArray(array, middleIndex+1, right);
MaxSubArrayInfo middleMaxInfo = findMaxCrossingSubArray(array, left, middleIndex, right);
return (leftMaxInfo>=rightMaxInfo&&leftMaxInfo>=middleMaxInfo) ? leftMaxInfo : ((rightMaxInfo>=leftMaxInfo&&rightMaxInfo>=middleMaxInfo) ? rightMaxInfo : middleMaxInfo);
}
}
int main(int argc, const char **argv)
{
int a[] = {13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7};
MaxSubArrayInfo result = findMaxSubArray(a, 0, 15);
cout<<"One max subarray info(index from 0) :" << endl;
cout<<"left index : " <<result.maxLeftIndex<<endl;
cout<<"right index : "<<result.maxRightIndex<<endl;
cout<<"max sum : "<<result.maxSum<<endl;
system("pause");
return 0;
}