求子数组的最大和(数组)
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;
}
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为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;
}
相关文章推荐
- 编程之美2.14 求子数组和的最大值(首尾相连)
- 求子数组的最大和
- 求子数组最大和的实例代码
- 算法讨论(二)---求子数组的最大和
- 求子数组的最大和问题
- 编程之美2.14扩展问题1 求子数组和的最大值(首尾可以相连)
- 二维数组中求子数组和最大
- 求子数组的最大和
- 求子数组的最大和
- 求子数组的最大和(O(n)和分治法O(nlogn))
- 【面试】求子数组的和的最大值
- 求子数组的最大和
- 求子数组最大和各种方法 各种。。
- 求子数组的最大和
- 求子数组的最大和
- 【面试题经典重温【原创】】求子数组的最大和
- (程序员面试题精选(03))-求子数组的最大和
- 3.求子数组的最大和
- 求子数组的最大和
- 求子数组的最大和