最大子数组问题,背景是股票买卖,也就是求一个数组的连续子数组的最大和,这个数组的元素一定是有负数的,要不然一定是所有元素之和。
用分冶法解决这个问题。
a[low,high]的任何连续子数组a[i,j]所处的位置必然满足下列三种情况:
- 完全位于左子数组a[low, mid]
- 完全位于右子数组a[mid + 1, high]
- 跨越中点
最大子数组一定是这三种情况的所有子数组的和最大者
而任何跨越中点的 子数组都由两个子数组a[i, mid] 和a[mid + 1, j]组成,只要求出形如a[i, mid] 和a[mid + 1, j]的最大子数组,然后将其合并即可。
#include <iostream>
#include <stdlib.h>
#define LENGTH 16
using namespace std;
typedef struct
{
int low;
int high;
int sum;
}parm;
parm find_max_crossing_array(int number[], int low, int mid, int high)
{
parm threeParm;
int sum = 0;
int leftsum = number[mid] - 1;
int left;
for(int i = mid; i >= low; i--)
{
sum += number[i];
if(sum > leftsum)
{
leftsum = sum;
left = i;
}
}
sum = 0;
int rightsum = number[mid + 1] - 1;
int right;
for(int i = mid+1; i <= high; i++)
{
sum += number[i];
if(sum > rightsum)
{
rightsum = sum;
right = i;
}
}
threeParm.low = left;
threeParm.high = right;
threeParm.sum = leftsum + rightsum;
return threeParm;
}
parm find_max_son_array(int number[], int low, int high)
{
int mid;
parm threeParmLeft;
parm threeParmRight;
parm threeParmCross;
parm threeParm;
//递归停止
if(low == high)
{
threeParm.low = low;
threeParm.high = high;
threeParm.sum = number[low];
return threeParm;
}
else
{
mid = (low + high) /2;
threeParmLeft = find_max_son_array(number, low, mid);
threeParmRight = find_max_son_array(number, mid + 1, high);
threeParmCross = find_max_crossing_array(number, low, mid, high);
if(threeParmLeft.sum > threeParmRight.sum && threeParmLeft.sum > threeParmCross.sum)
{
return threeParmLeft;
}
else if(threeParmRight.sum > threeParmLeft.sum && threeParmRight.sum > threeParmCross.sum)
{
return threeParmRight;
}
else
{
return threeParmCross;
}
}
}
int main()
{
int number[LENGTH] = {13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
parm threeParm;
threeParm = find_max_son_array(number,0,LENGTH - 1);
cout << threeParm.low << " " << threeParm.high << " " << threeParm.sum << endl;
system("PAUSE");
return 0;
}