算法导论分治算法
分治法:将数组尽可能分成规模相等的两部分,所以最大子数组无外乎三种情况
1.全在左数组a[low->mid]中
2.全在右数组a[mid+1->high]中
3.在左右中a[mid-i->mid+j]中
所以我们将问题进行细化,接下来的内容在代码中进行讲解
下面这道题的答案是43
#include"iostream"
#include"cstdio"
#define inf -99999999 //对求左右中间的数组中为左边最大和 和 右边最大和进行初始化,保证正确计算(因为要进行比较)
using namespace std;
int maxsubcross(int a[],int low,int mid,int high) //maxsubcross和maxsub函数小心返回值是整数(最大的子数组的和值)
{
int leftsum=inf;
int rightsum=inf;
int sum=0;
for(int i=mid;i>=low;i--)
{
sum+=a[i];
if(sum>=leftsum)
{
leftsum=sum;
}
}
sum=0;
for(int i=mid+1;i<=high;i++)
{
sum+=a[i];
if(sum>=rightsum)
{
rightsum=sum;
}
}
return leftsum+rightsum;
}
int maxsub(int a[],int low,int high)
{
int leftsum;
int rightsum;
int crosssum;
int mid=(low+high)/2;
if(low==high) //当无法再二分的时候,返回当前这个值就好(这个值最大)
{
return a[low];
}
else
{
leftsum=maxsub(a,low,mid); //目的是递归到底
rightsum=maxsub(a,mid+1,high); //目的是递归到底
crosssum=maxsubcross(a,low,mid,high); //目的是递归到底
if(leftsum>=rightsum&&leftsum>=crosssum)
{
return leftsum;
}
else
{
if(rightsum>=leftsum&&rightsum>=crosssum)
{
return rightsum;
}
else //leftsum和rightsum都不是最大的,那么就只有crosssum是最大的了
{
return crosssum;
}
}
}
}
int main()
{
int a[] = {13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7};
int length=sizeof(a)/sizeof(int);
cout<<maxsub(a,0,length-1)<<endl;
return 0;
}
深度思考1:
如果不仅要返回最大子数组的和,还要其初始位置和终止位置
添加全局变量每次更新进行记录就好
深度思考2:
如果不仅要返回最大子数组的和,还要其全部子数列的成员
添加全局数组,每次更新记录就好