Description
一个整数序列,选出其中连续且非空的一段使得这段和最大。
注意当题目要求输入输出的数据量很大时,尽量使用scanf和printf。 c++提供的cin和cout速度比较慢,有可能在读取数据和输出数据时导致超时。
输入格式
第一行是一个正整数N,表示了序列的长度(0=<N<=200000)。
第二行包含N个绝对值不大于10000的整数ai。
输出格式
一个整数,为最大的子段和。子段的最小长度为1。数据确保结果在类型int范围内。
输入样例
7
2 -4 3 -1 2 -4 3
输出样例
4
提示
【样例说明】
2,-4,3,-1,2,-4,3中,最大的子段和为4,该子段为第三元素至第五元素,即3,-1,2。
一、暴力算法
//暴力算法----超时 时间复杂度O(n^2)
#include <stdio.h>
int main()
{
int i, j,tempSum[200000] ={0}, maxSum, n, num[200000] = {0};
scanf("%d", &n);
for (i = 0; i < n; i++)
scanf("%d", &num[i]);
int temp = 0;
for (i = 0; i < n; i++)
{
temp+=num[i];
tempSum[i] = temp;
}
maxSum = tempSum[0];
for (i = 0; i < n; i++)
{
for (j = i+1; j < n; j++)
{
if (maxSum < tempSum[j] - tempSum[i] + num[i])
maxSum = tempSum[j] - tempSum[i] + num[i];
}
}
printf("%d\n", maxSum);
return 0;
}
//计算前缀和-在前一个代码的基础上进行了优化,加入min标记最小前缀和
//AC 时间复杂度O(n)
#include <stdio.h>
int main()
{
int i, j,tempSum[200000] ={0}, n, num[200000] = {0};
scanf("%d", &n);
for (i = 0; i < n; i++)
scanf("%d", &num[i]);
//计算前缀和
int temp = 0;
for (i = 0; i < n; i++)
{
temp+=num[i];
tempSum[i] = temp;
}
int min, max;
min = max = tempSum[0];
for (i = 1; i < n; i++)
{
if (min > tempSum[i])
min = tempSum[i];//记录最小前缀和的值
if (tempSum[i] - min > max)
max = tempSum[i] - min;//计算最大字段和,即最大前缀和 减去 最小前缀和
}
printf("%d\n", max);//输出结果
return 0;
}
二、分治法
//AC
#include <stdio.h>
int max(int a, int b, int c)
{
int temp = a > b ? a : b;
return temp > c ? temp : c;
}
int maxSum(int *num, int l, int r)
{
//递归结束条件
if (l == r)
return num[l];
int mid = l + (r-l)/2;//分左右两个区间
int leftSum = maxSum(num,l, mid);//左区间最大字段和
int rightSum = maxSum(num,mid+1, r);//右区间最大字段和
//从中间开始往左计算最大字段和
int i, temp = 0;
int lmax = num[mid];
for (i = mid; i >= l; i--)
{
temp += num[i];
if (lmax < temp)
lmax = temp;
}
//从中间开始往右计算最大字段和
int rmax = num[mid+1];
temp = 0;
for (i = mid+1; i <= r; i++)
{
temp += num[i];
if (rmax < temp)
rmax = temp;
}
return max(leftSum, rightSum, rmax+lmax);//比较左区间、右区间、两个区间合起来的字段和,返回最大字段和
}
int main()
{
int i, n, num[200000] = {0};
scanf("%d", &n);
for (i = 0; i < n; i++)
scanf("%d", &num[i]);
printf("%d\n", maxSum(num, 0,n-1));
return 0;
}
//最大字段和分治算法详解推荐博客:
// https://www.cnblogs.com/wkfvawl/p/11535615.html