您的位置:首页 > 其它

求子数组的最大和(数组)

2012-02-26 21:12 204 查看
题目:

输入一个整形数组,数组里有正数也有负数。

数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。

求所有子数组的和的最大值。要求时间复杂度为O(n)。

例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,

因此输出为该子数组的和18。

代码实现:

//coder:LEE

//20120226

#include<iostream>

#include<CASSERT>

using namespace std;

#define max(a,b) (((a) > (b)) ? (a) : (b))

int MaxSum2(int *A,int length)//动态规划,O(n)时间,O(n)空间

{

assert(A!=NULL&&length>0);

int *Start=new int[length];

int *All=new int[length];

Start[0]=A[0];

All[0]=A[0];

for (int i=1;i<length;i++)

{

Start[i]=max(Start[i-1]+A[i],A[i]);

All[i]=max(All[i-1],Start[i]);

}

return All[length-1];

}

int MaxSum(int* a,int length,int& beg,int &end)//扫描法,O(n)

{

assert(a!=NULL&&length>0);

int sum=a[0];

int max=a[0];

beg=0;

end=0;

for (int i=1;i<length;i++)

{

if(sum<0)

{

sum=a[i];

beg=i;

end=i;

}

else

sum+=a[i];

if(sum>max)

{

max=sum;

end=i;

}

}

return max;

}

int MaxSum(int *a,int left,int right)//二分法,O(nlgn)

{

assert(a!=NULL&&left>=0&&left<=right);

if(left==right)

return a[left];

if(left+1==right)

{

int max=(a[left]>a[right]?a[left]:a[right]);

int sum=a[left]+a[right];

return (max>sum?max:sum);//返回两个值最大或和最大的值

}

int mid=(left+right)/2;

int leftmax=MaxSum(a,left,mid-1);

int rightmax=MaxSum(a,mid+1,right);

int leftsum=a[mid];//从中间往左的和

int leftsummax=a[mid];//从中间往左和的最大值

int leftmid=mid-1;

while(leftmid>=left)

{

leftsum+=a[leftmid];

if((leftsummax<leftsum))

leftsummax=leftsum;

--leftmid;

}

int rightsum=a[mid];//从中间往右的和

int rightmid=mid+1;

int rightsummax=a[mid];//从中间往右的和

while (rightmid<=right)

{

rightsum+=a[rightmid];

if(rightsummax<rightsum)

rightsummax=rightsum;

++rightmid;

}

int midsum=leftsummax+rightsummax-a[mid];//比较左、右、中哪个最大

int temp=leftmax>rightmax?leftmax:rightmax;

return (midsum>temp?midsum:temp);

}

int HeadTailJoin(int* A,int length)

{

assert(A!=NULL&&length>=0);

int LToRSum=A[0];

int LToRMax=A[0];

int LToRTag=0;

int Sum;

for (int i=1;i<length;++i)

{

LToRSum+=A[i];

if (LToRSum>LToRMax)

{

LToRMax=LToRSum;

LToRTag=i;

}

}

int RToLSum=A[length-1];

int RToLMax=A[length-1];

int RToLTag=length-1;

for (i=length-2;i>=0;--i)

{

RToLSum+=A[i];

if (RToLSum>RToLMax)

{

RToLMax=RToLSum;

RToLTag=i;

}

}

if (LToRTag<RToLTag)

Sum=LToRMax+RToLMax;

else

Sum=LToRSum;

return(max(MaxSum2(A,length),Sum));

}

int main()

{

cout<<"动态规划法:"<<endl;

int a[]={1,-2,3,10,-4,7,2,-5};

cout<<MaxSum2(a,sizeof(a)/sizeof(int))<<endl;

int b[]={-1,-2,-3,-4,-5,-6};

cout<<MaxSum2(b,sizeof(b)/sizeof(int))<<endl;;

int d[]={-5,-4,-1,-3,-8,-1,-1,-1};

cout<<MaxSum2(d,sizeof(d)/sizeof(int))<<endl;

int c[]={1,1,1,1,1,1,1,1};

cout<<MaxSum2(c,sizeof(c)/sizeof(int))<<endl;

cout<<"分治法:"<<endl;

int e[]={1,-2,3,10,-4,7,2,-5};

cout<<MaxSum(e,0,7)<<endl;

int f[]={-1,-2,-3,-4,-5,-6};

cout<<MaxSum(f,0,5)<<endl;;

int g[]={-5,-4,-1,-3,-8,-1,-1,-1};

cout<<MaxSum(g,0,7)<<endl;

int h[]={1,1,1,1,1,1,1,1};

cout<<MaxSum(h,0,7)<<endl;

cout<<"head and tail join together!"<<endl;

int j[]={1,-2,3,10,-4,7,2,-5};

cout<<HeadTailJoin(j,sizeof(j)/sizeof(int))<<endl;

int k[]={-1,-2,-3,-4,-5,-6};

cout<<HeadTailJoin(k,sizeof(k)/sizeof(int))<<endl;;

int m[]={-5,-4,-1,-3,-8,-1,-1,-1};

cout<<HeadTailJoin(m,sizeof(m)/sizeof(int))<<endl;

int n[]={1,1,1,1,1,1,1,1};

cout<<HeadTailJoin(n,sizeof(n)/sizeof(int))<<endl;

cout<<"扫描法,并输出最大字数组位置:"<<endl;

int beg=0,end=0;

int s[]={1,-2,3,10,-4,7,2,-5};

cout<<MaxSum(s,sizeof(s)/sizeof(int),beg,end);

cout<<" beg:"<<beg<<" end:"<<end<<endl;

int q[]={-1,-2,-3,-4,-5,-6};

cout<<MaxSum(q,sizeof(q)/sizeof(int),beg,end);

cout<<" beg:"<<beg<<" end:"<<end<<endl;

int p[]={-5,-4,-1,-3,-8,-1,-1,-1};

cout<<MaxSum(p,sizeof(p)/sizeof(int),beg,end);

cout<<" beg:"<<beg<<" end:"<<end<<endl;

int z[]={1,1,1,1,1,1,1,1};

cout<<MaxSum(z,sizeof(z)/sizeof(int),beg,end);

cout<<" beg:"<<beg<<" end:"<<end<<endl;

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: