最大子段和(C++解法)

题目描述

给出一个长度为n的序列a,选出其中连续且非空的一段使得这段和最大。

输入格式

第一行是一个整数,表示序列的长度n。

第二行有n个整数,第i个整数表示序列的第i个数字a[i]。

输出格式

输出一行一个整数表示答案。

输入输出样例

输入 #1

7

2 -4 3 -1 2 -4 3

输出 #1

4

说明/提示

样例1解释:

选取 [3,5][3,5] 子段 {3,−1,2}{3,−1,2},其和为 44。

数据规模与约定:

  • 对于 40% 的数据,保证 n≤2×10的三次方n≤2×103。
  • 对于 100% 的数据,保证 1≤n≤2×10的五次方,−10的四次方≤ai​≤10的四次方。

分析:

解法1:

这道题需要我们在n个数中选取不大于n个数,使它们的和值最大,这就表明我们要在不知道总选择个数的前提下求出最大值。

我们先写基础的输入:

#include<iostream>
using namespace std;
int main()
{
    int n,i,a[200000];//注意a数组的大小
    cin>>n;
    for(i=1;i<=n;i++) cin>>a[i];
}

这里我的思路是将从第一位加到第m位(m是不大于n且大于零的数)存到f[m]中,例如:

位数(m)12345
输入(a数组)2-43-12
当前总和(f数组)2-2102

 这里我只取了数据的前五位,如果我们想用第2位到第4位的总和,只需要拿f[4]减f[2],就能得到,这里写出代码:

f[1]=a[1];
for(i=2;i<=n;i++)
	{
        f[i]=f[i-1]+a[i];//每个f[i]都等于f[i-1]+a[i](除了f[1])
	}
	for(i=1;i<=n;i++)
	{
		for(j=i;j<=n;j++)
		{
			sum=f[j]-f[i-1];
			maxi=max(maxi,sum);//比较大小
			sum=0;
		}
	}

 最后输出maxi就能得到值。

AC代码1:

#include<iostream>
using namespace std;
int main()
{
	int n,i,a[200000],f[200000],j,k,s1=1,maxi=-100000,sum=0;
	cin>>n;
	for(i=1;i<=n;i++) cin>>a[i];
    f[1]=a[1];
	for(i=1;i<=n;i++)
	{
		f[i]=f[i-1]+a[i];
	}
	for(i=1;i<=n;i++)
	{
		for(j=i;j<=n;j++)
		{
			sum=f[j]-f[i-1];
			maxi=max(maxi,sum);
			sum=0;
		}
	}
	cout<<maxi;
	return 0;
}

 解法2:

这种解法需要运用动态规划,思路是在每次输入时就直接计算和值比较大小并替换,整体更加简洁,并且不使用数组。

AC代码2:

#include<iostream>
using namespace std;
int main()
{
	int n,i,a,f=0,maxi=-100000;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		cin>>a;
		if(f+a>a) f=f+a;
		else f=a;
		maxi=max(maxi,f);
	}
	cout<<maxi;
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值