最大子序列求和问题
Posted yaopengcaiji
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最大子序列求和问题相关的知识,希望对你有一定的参考价值。
给定K个整数组成的序列{ N?1??, N?2??, ..., N?K??},“连续子列”被定义为{ N?i??, N?i+1??, ..., N?j?? },其中 1≤i≤j≤K。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。
输入格式:
输入第1行给出正整数K (≤);第2行给出K个整数,其间以空格分隔。
输出格式:
在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出0。
输入样例:
6
-2 11 -4 13 -5 -2
输出样例:
20
我写的代码如下:
1 #include <stdio.h> 2 3 4 int Maxsubseqsum(int a[],int n); 5 int main () 6 { 7 int n; 8 int a[100005]; 9 int sum=0; 10 scanf("%d", &n); 11 for(int i=0; i<n; i++) 12 { 13 scanf("%d",&a[i]); 14 } 15 sum=Maxsubseqsum(a,n); 16 printf("%d ",sum); 17 return 0; 18 } 19 int Maxsubseqsum(int a[],int n)//求最大子序列长度函数 20 { 21 int thissum,maxsum; 22 int i; 23 thissum=maxsum=0; 24 for(i=0; i<n; i++) 25 { 26 thissum+=a[i]; 27 28 if(thissum>maxsum) 29 maxsum=thissum; 30 else if(thissum<0) 31 32 thissum=0; 33 34 35 36 } 37 return maxsum; 38 }
这个程序的时间复杂度是比较好的,大概是O(n)吧。当然,这道题还可以用暴力三个循环给暴力出来,但时间复杂度太高,O(n^3),不推荐。
好,现在解释一下吧。
用样例讲吧,
6
-2 11 -4 13 -5 -2
6个数存进数组a[]中,然后进入函数Maxsubseqsum()中,传进数组长度n,和数组元素a[]。
在函数体中,首先定义一个当前总和thissum和子序列总和maxsum。
初始化它们为0,然后一个循环搞定。
在循环中,我们首先将序列的第一个数给thissum,本例中就是将-2给thissum,判断此时的thissum是否大于maxsum,显然,-2<maxsum,
好!第一个if不成立,进入else if ,发现-2<0,那我们将thissum重新置为0。第一个数结束。
现在开始第二个数,也就是11,thissum=11,此时thissum>maxsum=0,将maxsum置为11。且此时的thissum=11>0,我们不将它置为0,它还是11.
以此列推,此时,thissum=11+(-4)=7,时,比maxsum小,就不把它给maxsum了。但是它大于0,thissum还是7.
接下来,thissum=7+13=20时,thissum=20>maxsum=11,我们就可以将maxsum置为20了。显然此时thissum=20大于0,它暂时不置为0
遇到-5,thissum=15,它还不能撼动maxsum的20,遇到-2时,thissum=13,还是无法撼动maxsum的20,
所以,最终maxsum=20,函数返回了maxsum=20.
有点啰嗦,但详细。若有错误请指正。
2.这是稍难的,求最大子序列的同时请给出此最大子序列的头和尾相对应的数值。
#include<bits/stdc++.h>
using namespace std;
void Maxsubseqsum(int a[],int n);
int main ()
{
int n;
int a[100];
int sum=0;
scanf("%d", &n);
for(int i=0; i<n; i++)
{
scanf("%d",&a[i]);
}
Maxsubseqsum(a,n);
return 0;
}
void Maxsubseqsum(int a[],int n)
{
int thissum,maxsum;
int i;
int cnt=0;///头的位置
int outs=0;///尾的位置
int flag=0,flag_max=0;///单最大值改变时flag_max发生改变
int mfirst=0;///可能的头
thissum=maxsum=0;
for(i=0; i<n; i++)
{
thissum+=a[i];
if(thissum>maxsum)
{
flag_max=1;
if(flag==0)
{
cnt=mfirst;
flag=1;
}
maxsum=thissum;
outs=i;
}
else if(thissum<0)
{
mfirst=i+1;
thissum=0;
flag=0;
}
}
if (flag_max==0)
{
printf("0 %d %d
",a[0],a[n-1]);
}
else
{
printf("%d %d %d
",maxsum,a[cnt],a[outs]);
}
}
以上是关于最大子序列求和问题的主要内容,如果未能解决你的问题,请参考以下文章