最大连续子段和 (HDU 1003)
1.问题描述
给定一串整数, 例如 6 -1 5 4 -7, 求最大连续子段和?
2.算法介绍
此题不能暴力, O(n^2)的时间复杂度必然超时。
考虑如下算法:
设Mi表示前i个整数包含第i个整数的最大连续子段和。
sum (i, j) 表示第i个整数到第j个整数的和, 最大连续子段和就是max sum (i, j), 也就是max Mi;
情况一: 如果M(i-1) <= 0, 则 Mi = 第i个整数
情况二: 如果M(i - 1) > 0, 则 Mi = M(i - 1) + 第i个整数
以上两种情况, 不管第i个整数如何都成立。
所以, 可以在O(n)的时间内求出所有的Mi, 记录最大Mi即为所求的最大连续子段和。
在杭电上的1003题, 还需要计算出最大连续子段的始末位置。
起始位置只在一种情况下被改变, 就是当某个Mi <= 0, 并且之后的某个Mj > max Mi;
3. 源代码
#include <stdio.h>
int main()
{
int i;
int T, N;
int count, temp;
int max, start, end;
int number, sum;
scanf ("%d", &T);
count = 1;
while (T --)
{
scanf ("%d", &N);
temp = end = start = 0;
max = -100000000;
sum = 0;
for (i = 0; i < N; i ++)
{
scanf ("%d", &number);
sum += number;
if (max < sum)
{
max = sum;
start = temp; // 旧的起始点被替换
end = i;
}
if (sum < 0)
{
sum = 0;
temp = i + 1; // 可能的起始点 因为以后的值累加后可能有超过max的情况
}
}
printf ("Case %d:\n", count ++);
printf ("%d %d %d\n", max, start + 1, end + 1);
if (T > 0)
{
printf ("\n");
}
}
return 0;
}