最大子序列求和问题

Posted yaopengcaiji

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最大子序列求和问题相关的知识,希望对你有一定的参考价值。

给定K个整数组成的序列{ N?1??, N?2??, ..., N?K??},“连续子列”被定义为{ N?i??, N?i+1??, ..., N?j?? },其中 1ijK。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -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]);

}
}

 




























































以上是关于最大子序列求和问题的主要内容,如果未能解决你的问题,请参考以下文章

c语言子序列问题

算法分析之最大子段求和

[HDOJ 1003]动态规划法求和最大的连续子序列

子序列求和问题

codeforces的dp专题

最大联通子数组求和