题目:从一段输入的序列中,找出其连续子序列的最大值:k={0,max{A0,A1,A2.....}},Ai是其输入序列的连续子列。
测试数据:
序列:-2 11 -4 13 -5 -2,则最大子序列和为20。
序列:-6 2 4 -7 5 3 2 -1 6 -9 10 -2,则最大子序列和为16。
算法一:利用递归:其时间复杂度(Nlog(N))
解析:递归思想是:将序列分为三个部分,左侧部分和、右侧部分和(其中分法用的二分法方式)和包括左右部分整体部分序列和。当序列逐次的遍历到最后只有单个元素后,将相邻两个单元素和这两个元素组成的集合,这三个集合相互比较,得到一个最大值(在这里{0},{1},{0,1}得到最大值 在同{2},{1,2}比较),这里不需要{0,1}{1,2}这样来比较,(这样就可以省略相当一部分相同操作)同样可以得到最大子序列。
代码如下:
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
vector <int>a;
//采用的是递归来进行算法时间复杂度减少(Nlog(N))
long maxSumRec( int left,int right,int *startpoint,int*endpoint)
{ if(left==right)
{
if(a[left]>0)
return left;
else
return 0;
}
int begin=-1, end=-1;
int centra=(left+right)/2;
int leftStart=left,leftEnd=centra, rightStart=centra+1,rightEnd=right;
long maxleftsum=maxSumRec(left,centra,&leftStart,&leftEnd);
long maxrightsum=maxSumRec(centra+1,right,&rightStart,&leftEnd);
////求出以左边对后一个数字结尾的序列最大值rr
long maxleftBorderSum=0, leftBordersum=0;
for(int i=centra;i>=left;i--)
{
leftBordersum+=a[i];
if(maxleftBorderSum<leftBordersum)
{
maxleftBorderSum=leftBordersum;
begin=i;
}
}
//求出以右边对后一个数字结尾的序列最大值
long maxRightBorderSum = 0, rightBorderSum = 0;
for (int j = centra+1; j <= right; j++)
{
rightBorderSum += a[j];
if (rightBorderSum > maxRightBorderSum)
{
maxRightBorderSum = rightBorderSum;
end=j;
}
}
long c=maxleftBorderSum+ maxRightBorderSum ;
//计算三者中最大值
//long a=maxleftsum, b= maxrightsum, c=maxleftBorderSum+ maxRightBorderSum ;
{
long tmp;
if(maxleftsum>maxrightsum)
{
*startpoint=leftStart;
*endpoint=leftEnd;
tmp=maxleftsum;
}
else
{
tmp=maxrightsum;
}
if(tmp>c)
{
*startpoint=rightStart;
*endpoint=rightEnd;
cout<<*startpoint<<endl;
cout<<*endpoint<<endl;
return tmp;
}
else
{
*startpoint=begin;
*endpoint=end;
return c;
}
}
}
long MaxSequenceValue()
{ int start=-55,end=55;
int k= maxSumRec(0,a.size()-1,&start,&end);
cout<<start<<endl;
cout<<end<<endl;
return k;
}
int main()
{
int num;
while( scanf("%d",&num)==1 )
{
a.push_back(num);
}
long MAX=MaxSequenceValue( );
cout<<MAX<<endl;
return 0;
}
算法4,采用的是联机算法:(由于最大子序列的Start点不可能是负值,所以可以对其省去)
具体代码如下:
#include<cstdio> #include<iostream> #include<vector> using namespace std; vector<int>a; int N; int MAXSeq4(int *left1,int *right1) { long maxsum4=0,thissum4=0;int begin=0; //求最大子序列中,最大子序列开始值一定不可能是负值,所以我们可以将其抛弃 for(int j=0;j<a.size();j++) { thissum4+=a[j]; if(maxsum4<thissum4) { maxsum4=thissum4; *left1=begin; *right1=j; } else if(thissum4<0) { thissum4=0; begin=j+1; } } return maxsum4; } int main() { cout<<"请输入您要输入序列总元素"; cin>>N; int num;int count=0;int max,left=0,right=0; while( N-- ) { //scanf("%d",&num);这句话用来进行测试的 num=(int)(rand()%100-121); // cout<<num<<" "; if(num<0) count++; a.push_back(num); } if(count==a.size()-1) { max=0; cout<<"MAX=:"<<max<<endl; } else { max=MAXSeq4(&left,&right); cout<<"("<<left<<','<<right<<"):"<<max<<endl; } return 0; }