子串和

子串和

时间限制: 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;
}

猜你喜欢

转载自blog.csdn.net/qq_40912854/article/details/80598937