这两题是一个意思,都是环形的最大子段和,把数组范围改一下,同样的代码就能过。
通常想到的办法是将数组扩大一倍,然后求n个n长度的最大子段和,然后再取一个最大值,但是这两题数据量都很大,两重for循环会超时。
其实,与线性的相比,环形的就是多了一步:求首位相连的串的最大子段和,这个怎么求?可以通过求首尾不相连的串的最小字段和min,然后把所有数字的总和减去min,就是首尾相连的串的最大子段和,其实就是,所有数字总和 - 线性的串的最小子段和 = 环形的串的最大子段和。
环形的串的最大子段和已经求出来,但是上面那种方法没有考虑到最小子段和包含头尾两个数字时的情况,所以还要再对线性的串求最大子段和,取两者中较大的那个输出。
#include <stdio.h>
long long a[100010];
int main (void)
{
int n;
while(scanf("%d", &n) != EOF)
{
int i;
long long sum = 0, b1 = 0, b2 = 0;
long long max1 = -0x3f3f3f3f, min = 0x3f3f3f3f;
for(i = 0; i < n; i++)
{
scanf("%lld", &a[i]);
sum += a[i];
//求线性的串的最大子段和
if(b1 > 0)
b1 += a[i];
else
b1 = a[i];
if(b1 > max1)
max1 = b1;
//求线性的串的最小字段和
if(b2 < 0)
b2 += a[i];
else
b2 = a[i];
if(b2 < min)
min = b2;
}
long long max2 = sum - min;//环形的串的最大子段和
printf("%lld\n", max2 > max1 ? max2 : max1);//取较大的输出
}
return 0;
}