100题_03 最大子序列和
题目:
输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18。
请参考:
http://www.cnblogs.com/youwang/archive/2010/07/16/1778929.html
问题扩展:
给定一个序列1,2,3,4,5,6,7,8 ,在首尾相连的情况下求S的一段连续序列,使得序列和的绝对值最大.输出这个最大值。
http://tianwei.dlut.edu.cn:8000/problem/show/1310
可以分两种情况进行考虑,第一种是不越过1和8的情况(同上面的问题),另外一种是越过1和8的情况。对于第二种情况,可以让总和减去除1和8外的最小子序列和。
代码:
#include <cstdio>
#include <cmath>
using namespace std;
int su;
int s[100000];
int f[100000];
int max_seq(int a[], int n)
{
int i;
f[0] = a[0];
int max = a[0];
for (i = 1; i < n; i++)
{
f[i] = f[i-1] > 0 ? f[i-1] + a[i] : a[i];
if (f[i] > max)
{
max = f[i];
}
}
return max;
}
int min_seq(int a[], int n)
{
int i;
f[0] = a[0];
int min = a[0];
for (i = 1; i < n; i++)
{
f[i] = f[i-1] < 0 ? f[i-1] + a[i] : a[i];
if (f[i] < min)
{
min = f[i];
}
}
return min;
}
int sum(int a[], int n)
{
int s = 0;
for (int i = 0; i <n; i++)
{
s += a[i];
}
return s;
}
int max_seq_over(int a[], int n)
{
return su - min_seq(&a[1], n - 2);
}
int min_seq_over(int a[], int n)
{
return su - max_seq(&a[1], n - 2);
}
int max_seq_loop_abs(int a[], int n)
{
if (n == 1)
{
return abs(a[0]);
}
if (n == 2)
{
int e = abs(a[0]);
int f = abs(a[1]);
int g = abs(a[0] + a[1]);
if (f > e )
{
e = f;
}
if (g > e)
{
e = g;
}
return e;
}
su = sum(a, n);
int max = max_seq(a, n);
int tmp = abs(min_seq(a, n));
if (tmp > max)
{
max = tmp;
}
tmp = max_seq_over(a, n);
if (tmp > max)
{
max = tmp;
}
tmp = abs(min_seq_over(a, n));
if (tmp > max)
{
max = tmp;
}
return max;
}
int main()
{
int n, i;
while (scanf("%d", &n) != EOF)
{
for (i = 0; i < n; i ++)
{
scanf("%d", &s[i]);
}
printf("%d ", max_seq_loop_abs(s, n));
delete[] s;
}
return 0;
}
#include <cmath>
using namespace std;
int su;
int s[100000];
int f[100000];
int max_seq(int a[], int n)
{
int i;
f[0] = a[0];
int max = a[0];
for (i = 1; i < n; i++)
{
f[i] = f[i-1] > 0 ? f[i-1] + a[i] : a[i];
if (f[i] > max)
{
max = f[i];
}
}
return max;
}
int min_seq(int a[], int n)
{
int i;
f[0] = a[0];
int min = a[0];
for (i = 1; i < n; i++)
{
f[i] = f[i-1] < 0 ? f[i-1] + a[i] : a[i];
if (f[i] < min)
{
min = f[i];
}
}
return min;
}
int sum(int a[], int n)
{
int s = 0;
for (int i = 0; i <n; i++)
{
s += a[i];
}
return s;
}
int max_seq_over(int a[], int n)
{
return su - min_seq(&a[1], n - 2);
}
int min_seq_over(int a[], int n)
{
return su - max_seq(&a[1], n - 2);
}
int max_seq_loop_abs(int a[], int n)
{
if (n == 1)
{
return abs(a[0]);
}
if (n == 2)
{
int e = abs(a[0]);
int f = abs(a[1]);
int g = abs(a[0] + a[1]);
if (f > e )
{
e = f;
}
if (g > e)
{
e = g;
}
return e;
}
su = sum(a, n);
int max = max_seq(a, n);
int tmp = abs(min_seq(a, n));
if (tmp > max)
{
max = tmp;
}
tmp = max_seq_over(a, n);
if (tmp > max)
{
max = tmp;
}
tmp = abs(min_seq_over(a, n));
if (tmp > max)
{
max = tmp;
}
return max;
}
int main()
{
int n, i;
while (scanf("%d", &n) != EOF)
{
for (i = 0; i < n; i ++)
{
scanf("%d", &s[i]);
}
printf("%d ", max_seq_loop_abs(s, n));
delete[] s;
}
return 0;
}
本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名小橋流水(包含链接)。如您有任何疑问或者授权方面的协商,请给我发邮件。