子串和
时间限制:
5000 ms | 内存限制:
65535 KB
难度:
3
-
描述
- 给定一整型数列{a1,a2...,an},找出连续非空子串{ax,ax+1,...,ay},使得该子序列的和最大,其中,1<=x<=y<=n。
-
输入
-
第一行是一个整数N(N<=10)表示测试数据的组数)
每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的一行里有n个整数I(-100=<I<=100),表示数列中的所有元素。(0<n<=1000000)
输出
- 对于每组测试数据输出和最大的连续子串的和。 样例输入
-
1 5 1 2 -1 3 -2
样例输出
-
5
提示
- 输入数据很多,推荐使用scanf进行输入
无论给出的序列是什么样的,他的最大子串和肯定是存在的,所以现在的出发点就基于此,一个变量 tp 统计每次增加一个元素的值能达到的数值,另一个 sum 来记录最大值,每加入一个元素,tp 改变,比较 tp 是否超过了现在的最大值 sum 如果超过了,那么就更新 sum 为 tp的值,因为现在最大的值是 tp 的值了,然后来讨论 tp 的更新处理,比较容易想到,如果本来前 n 项的和(从某一个起点开始的tp 的值)还是正的,结果多加了后一项之后,突然这个 tp 变成负的了,那么证明这一项是个非常大的负数,那么最大的子串和的序列肯定不包含这一个元素,然后继续求子串和,就直接从后一项开始了.把刚才那一项跳过,就这样更新下去,最终求得的肯定是最大子串的和,因为我们只在当前子串和 tp 比 sum 大的时候进行更新,否则不更新,而 tp 这个变量,可以把所有可能达到最大和的子串的和都求了一遍,所以最大的和一定能记录下来
#include<stdio.h>
#define M 1000001
int a[M];
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
int n,i,temp=0,max=-M;//这个题有一个陷阱,就是初始的值一定要很小。假设让max=0,如果所输入的数组元素之和本身全为负,自己体会
scanf("%d",&n);
for (i=0;i<n;i++)
scanf("%d",&a[i]);
for (i=0;i<n;i++)
{
temp += a[i];
if (temp>max)
max = temp;
if (temp<0)
temp = 0;
}
printf("%d\n",max);
}
return 0;
}