最大子段和问题。给定由n个整数组成的序列,求序列中子段的最大和,若所有整数均为负整数时定义最大子段和为0。
输入格式:
第一行输入整数个数n(1≤n≤10000),再依次输入n个整数。
输出格式:
输出第一行为最大子段和,第二行为子段第一个数和最后一个数在整个序列中的位序。
输入样例1:
5
-2 11 -4 13 -5 -2
输出样例1:
20
2 4
这是前缀和的解法,时间复杂度为O(n2)。这题让输出最大子串的和还有对应的位序(即数组下标加1),如果只要求输出和,用dp动态规划,时间复杂度可以降到o(n)。如果这题暴力求解时间复杂度为o(n3)。除了此题为例的以为前缀和以外,还有二维前缀。
#include <stdio.h>
#define maxn 10000
int num[maxn],pre[maxn];
int flag=-1;
void mssum(int n,int a[])
{
int i,j,max=-1,temp1,temp2;
for(i=0;i<n;i++)
{
for(j=i;j<n;j++)//注意下标是从j=i开始,如果从0开始就错了
{
if(i==0)//特判一下i=0;,可以理解从第一个元素到底j+1个元素的和
{
if(pre[j]>max)
{
max=pre[j];
temp1=i;
temp2=j;//记录当前最大子串的数组下标
}
}
else
{
if(pre[j]-pre[i-1]>max)//一般情况,减去的是i-1下标的前缀数组
{
max=pre[j]-pre[i-1];
temp1=i;
temp2=j;
}
}
}
}
printf("%d\n%d %d",max,temp1+1,temp2+1);//输出结果
}
int main()
{
int n,i;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&num[i]);
if(num[i]>0)
flag=1;//这个是标记是否全是负数,如果全是负数,则输出0
if(i==0)//初始化前缀和
pre[i]=num[i];
else
pre[i]=pre[i-1]+num[i];
}
if(flag==-1)
printf("0");
else
mssum(n,num);
return 0;
}
有时间再写写dp的,浙大数据结构第一课就有这个例题。