1.概念
求数组的和最大的非空连续子数组,这样的连续的子数组称为最大子数组(maximum subarray)
2.常规方法(O^3)
/* 最大子段和问题 O^3*/
#include <iostream>
using namespace std;
//打印数组
void printArray(int *arr, int strat, int last)
{
for (int i = strat; i <= last; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
//求最大子段和
int MaxSum(int len, int *arr, int& besti, int &bestj)
{
int sum = 0;
for(int i = 1; i <= len; i++)
{
for (int j = i; j <= len; j++)
{
int thissum = 0;
for (int k = i; k <= j; k++)
{
thissum += arr[k];
}
if (thissum > sum)
{
sum = thissum; //最大字段和
besti = i; //最大子段和开始位置
bestj = j; //最大子段和结束位置
}
}
}
return sum;
}
int main()
{
int len = 0, i = 0, j = 0;
int array[16] = { 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7 };
//数组长度
len = sizeof(array) / sizeof(*array);
//打印原始数组
cout << "The Array is: " << endl;
printArray(array, 0, len-1);
//求最大子段和
cout << "The MaxSum is: " << endl;
cout << MaxSum(len, array, i, j) << endl;
//打印最大子段
cout << "The MaxSumArray is: " << endl;
printArray(array, i, j);
system("pause");
return 0;
}
/*
The Array is:
13 -3 -25 20 -3 -16 -23 18 20 -7 12 -5 -22 15 -4 7
43
The MaxSumArray is:
18 20 -7 12
请按任意键继续. . .
*/
3.分治策略解决最大子段和问题(nlgn)
分治策略在每层递归时都有三个步骤:
A 分解原问题为若干子问题,这些子问题是原问题的规模较小的实例。
B 解决这些子问题,递归地求解各子问题。然而,若子问题的规模足够小,则直接求解。
C 合并这些子问题的解成原问题的解。
分治策略的求解分析
假设要寻找子数组A[low…high]的最大子数组。使用分治策略要将子数组划分为两个规模尽量相等的子数组。先找到中间位置mid,然后考虑求解两个子数组A[low…mid]和A[mid+1…high]。
A[low…high]的任何连续子数组A[i…j]所处的位置必然是以下三种情况之一:
A 完全位于子数组A[low…mid]中,low≤i≤j≤mid。
B 完全位于子数组A[mid+1…high],mid+1≤i≤j≤high。
C 跨越了中点,low≤i≤mid≤j≤high。
/* 分治思想下的最大子段和问题 nlgn*/
#include <iostream>
using namespace std;
//打印数组
void PrintArray(int *arr, int strat, int last)
{
for (int i = strat; i <= last; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
//寻找最大子段和
int MaxSubSum(int *arr, int low, int high, int& bestl, int& bestr)
{
int sum = 0, mid = 0, leftSum = 0, rightSum = 0;
int sl = 0, sr = 0, leftS = 0, rightS = 0;
int l = 0, r = 0;
if (low == high)//只有一个元素
{
sum = arr[low];
}
else
{
mid = (low + high) / 2;//中间位置
//分治思想
leftSum = MaxSubSum(arr, low, mid, l, r);
rightSum = MaxSubSum(arr, mid + 1, high, l, r);
//左半部分最大子段和
for (int i = mid; i >= low; i--)
{
leftS += arr[i];
if (leftS > sl)
{
sl = leftS;
bestl = i;
}
}
//右半部分最大子段和
for (int i = mid + 1; i <= high; i++)
{
rightS += arr[i];
if (rightS > sr)
{
sr = rightS;
bestr = i;
}
}
sum = sl + sr;//跨越中点的最大子段和
if (sum < leftSum)
{
sum = leftSum;
}
if (sum < rightSum)
{
sum = rightSum;
}
}
return sum;
}
int main()
{
int len = 0, l = 0, r = 0;
int array[] = { 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7 };
//数组长度
len = sizeof(array) / sizeof(*array);
//打印原始数组
cout << "The Array is: " << endl;
PrintArray(array, 0, len - 1);
//寻找最大子数组
cout << "The MaxSum is: " << endl;
cout << MaxSubSum(array, 0, len - 1, l, r) << endl;
///打印最大子数组
cout << "The MaxSumArray is: " << endl;
PrintArray(array, l, r);
system("pause");
return 0;
}
/*
The Array is:
13 -3 -25 20 -3 -16 -23 18 20 -7 12 -5 -22 15 -4 7
The MaxSum is:
43
The MaxSumArray is:
18 20 -7 12
请按任意键继续. . .
*/