Given a sequence of K integers { N1, N2, ..., NK }. A continuous subsequence is defined to be { Ni, Ni+1, ..., Nj } where 1≤i≤j≤K. The Maximum Subsequence is the continuous subsequence which has the largest sum of its elements. For example, given sequence { -2, 11, -4, 13, -5, -2 }, its maximum subsequence is { 11, -4, 13 } with the largest sum being 20.
Now you are supposed to find the largest sum, together with the first and the last numbers of the maximum subsequence.
Input Specification:
Each input file contains one test case. Each case occupies two lines. The first line contains a positive integer K (≤10000). The second line contains K numbers, separated by a space.
Output Specification:
For each test case, output in one line the largest sum, together with the first and the last numbers of the maximum subsequence. The numbers must be separated by one space, but there must be no extra space at the end of a line. In case that the maximum subsequence is not unique, output the one with the smallest indices i and j (as shown by the sample case). If all the K numbers are negative, then its maximum sum is defined to be 0, and you are supposed to output the first and the last numbers of the whole sequence.
Sample Input:
10
-10 1 2 3 4 -5 -23 3 7 -21
Sample Output:
10 1 4
以上是原题内容。
需要注意的是:
1)相比输出最大子列和,该题需要输出最大子列和的首尾数字,注意不是下标!(一开始以为是下标25分只拿了3分)。
2)有一个1分的要求是最大子列和含有前面一段0,需要将输出结果的最大子列和首个数字包括这个0(这一问题没读懂折腾了好久给自己整笑了hh)。
3)如果全是负数,输出结果的头尾应该是序列的头尾;如果全是负数和零,输出结果最大子列和头尾应该都是0。
跟着mooc的视频试了一下o(N^3)、o(N^2)、o(NlogN)、o(N)四种算法;在不输出子列和头尾的情况下,o(N^3)的算法测试OJ罢工了,o(N^2)在100000个随机数的时候用时3334ms,o(NlogN)在100000个随机数用时12ms,o(N)在100000个随机数下用时10ms。
以下是使用o(N)复杂度的算法解这道题。
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
int *MaxSubseqSum4(int *n,int k);
int main(){
int *result,k,n[100000]={0};
scanf("%d",&k);
for(int i=0;i<k;i++){
scanf("%d",&n[i]);
}
result=MaxSubseqSum4(n,k);
printf("%d %d %d",result[0],result[1],result[2]);
free(result);
return 0;
}
int* MaxSubseqSum4(int *n,int k){
int thissum=0,maxsum=0,cnt=0;
int *result=(int*)malloc(sizeof(int)*3);
result[1]=0;
bool exist_0=false;
for(int i=0;i<k;i++){
thissum+=n[i];
cnt++;
if(thissum>maxsum){
maxsum=thissum;
result[2]=n[i];
result[1]=n[i-cnt+1];
}else if(thissum<0){
thissum=0;
cnt=0;
}else if(thissum==0){
exist_0 = true;
}
}
result[0]=maxsum;
if(maxsum==0&&exist_0){
result[1]=0;
result[2]=0;
}else if(maxsum==0){
result[1]=n[0];
result[2]=n[k-1];
}
return result;
}
以下是前面讲的四种算法复杂度的C语言实现,按o(N^3)、o(N^2)、o(NlogN)、o(N)顺序分别是MaxSubseqSum(1-4)四个函数。
#include<stdio.h>
int max(int a,int b,int c){
return a>b?(a>c?a:c):(b>c?b:c);
}
int DivideandConquer(int *n,int left,int right);
int MaxSubseqSum1(int *n,int k);
int MaxSubseqSum2(int *n,int k);
int MaxSubseqSum3(int *n,int k);
int MaxSubseqSum4(int *n,int k);
int main(){
int sum,k,n[100000]={0};
scanf("%d",&k);
for(int i=0;i<k;i++){
scanf("%d",&n[i]);
}
sum=MaxSubseqSum4(n,k);
printf("%d",sum);
return 0;
}
int MaxSubseqSum4(int *n,int k){
int thissum=0,maxsum=0;
for(int i=0;i<k;i++){
thissum+=n[i];
if(thissum>maxsum){
maxsum=thissum;
}else if(thissum<0){
thissum=0;
}
}
return maxsum;
}
int DivideandConquer(int *n,int left,int right){
int maxleftsum=0,maxrightsum=0;
int maxleftbordersum=0,maxrightbordersum=0;
int leftbordersum=0,rightbordersum=0;
int center=(left+right)/2;
if(left==right){
if(n[left]>0) return n[left];
else return 0;
}
maxleftsum=DivideandConquer(n,left,center);
maxrightsum=DivideandConquer(n,center+1,right);
for(int i=center;i>=left;i--){
leftbordersum+=n[i];
if(leftbordersum>maxleftbordersum) maxleftbordersum=leftbordersum;
}
for(int i=center+1;i<=right;i++){
rightbordersum+=n[i];
if(rightbordersum>maxrightbordersum) maxrightbordersum=rightbordersum;
}
return max(maxleftsum,maxrightsum,maxleftbordersum+maxrightbordersum);
}
int MaxSubseqSum3(int *n,int k){
return DivideandConquer(n,0,k-1);
}
int MaxSubseqSum2(int *n,int k){
int thissum=0,maxsum=0;
for(int i=0;i<k;i++){
thissum=0;
for(int j=i;j<k;j++){
thissum+=n[j];
if(thissum>maxsum){
maxsum=thissum;
}
}
}
return maxsum;
}
int MaxSubseqSum1(int *n,int k){
int thissum=0,maxsum=0;
for(int i=0;i<k;i++){
for(int j=i;j<k;j++){
thissum=0;
for(int m=i;m<j;m++){
thissum+=n[m];
if(thissum>maxsum){
maxsum=thissum;
}
}
}
}
return maxsum;
}