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

题目:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值