引言
这道题在很多的笔试面试和研究生机试中都出现过很多次,并且这道题不是很难想出来,所以还是非常的重要的,话不多说,直接开讲。
一、题目描述
给定一个包含 K 个整数的序列 N 1 , N 2 , … , N K 。 给定一个包含 K 个整数的序列 {N1,N2,…,NK}。 给定一个包含K个整数的序列N1,N2,…,NK。
连续子序列定义为 N i , N i + 1 , … , N j ,其中 1 ≤ i ≤ j ≤ K 。 连续子序列定义为 {Ni,Ni+1,…,Nj},其中 1≤i≤j≤K。 连续子序列定义为Ni,Ni+1,…,Nj,其中1≤i≤j≤K。
最大子序列是指序列内各元素之和最大的连续子序列。 最大子序列是指序列内各元素之和最大的连续子序列。 最大子序列是指序列内各元素之和最大的连续子序列。
例如,给定序列 − 2 , 11 , − 4 , 13 , − 5 , − 2 ,它的最大子序列为 11 , − 4 , 13 ,其各元素之和为 20 。 例如,给定序列 {−2,11,−4,13,−5,−2},它的最大子序列为 {11,−4,13},其各元素之和为 20。 例如,给定序列−2,11,−4,13,−5,−2,它的最大子序列为11,−4,13,其各元素之和为20。
现在你需要求出最大子序列的各元素之和。 现在你需要求出最大子序列的各元素之和。 现在你需要求出最大子序列的各元素之和。
输入格式
输入格式
输入格式
第一行包含一个整数
K
。第二行包含
K
个整数。
第一行包含一个整数 K。第二行包含 K 个整数。
第一行包含一个整数K。第二行包含K个整数。
输出格式
输出格式
输出格式
输出一个整数,表示最大子序列的各元素之和。
输出一个整数,表示最大子序列的各元素之和。
输出一个整数,表示最大子序列的各元素之和。
设最大子序列为 N i , N i + 1 , … , N j ,如果答案不唯一,则选择 i 更小的解,如果仍不唯一,则选择 j 更小的解。 设最大子序列为 {Ni,Ni+1,…,Nj},如果答案不唯一,则选择 i 更小的解,如果仍不唯一,则选择 j 更小的解。 设最大子序列为Ni,Ni+1,…,Nj,如果答案不唯一,则选择i更小的解,如果仍不唯一,则选择j更小的解。
注意,我们规定,如果所有
K
个数字均为负数,则其最大和定义为
0
,并且应该输出整个序列的第一个数字
注意,我们规定,如果所有 K 个数字均为负数,则其最大和定义为 0,并且应该输出整个序列的第一个数字
注意,我们规定,如果所有K个数字均为负数,则其最大和定义为0,并且应该输出整个序列的第一个数字
和最后一个数字。
和最后一个数字。
和最后一个数字。
数据范围
数据范围
数据范围
1
≤
K
≤
10000
,
序列内元素的绝对值不超过
1
0
5
。
1≤K≤10000,序列内元素的绝对值不超过 10^5。
1≤K≤10000,序列内元素的绝对值不超过105。
二、思路1:DP
思路:
这道题可以拿
D
P
DP
DP 来做,
f
[
i
]
f[i]
f[i] 代表以
i
i
i 为结尾的最大子序列和,就只有两种情况跟上一个数合并,要么自己另成一个新的开始,然后在这两种选择中选最大,最后再求最大值即可。
示例代码:
#include <iostream>
using namespace std;
const int N = 1e4+10;
int n;
int a[N], f[N];
int main()
{
cin >> n;
for(int i = 1; i <= n; ++i) cin >> a[i];
int res = 0;
for(int i = 1; i <= n; ++i)
{
f[i] = max(f[i-1] + a[i], a[i]);
if(f[i] > res) res = f[i];
}
cout << res << endl;
return 0;
}
三、思路2:贪心
思路:
贪心其实就是如果连续区间的和为非负,那么就一直加下去,否则就从当前重新开始。
示例代码:
#include <iostream>
using namespace std;
const int N = 1e4+10;
int n;
int a[N];
int main()
{
cin >> n;
for(int i = 1; i <= n; ++i) cin >> a[i];
int sum = 0, res = -2e9;
for(int i = 1; i <= n; ++i)
{
sum += a[i];
res = max(res, sum);
if(sum < 0) sum = 0;
}
cout << res << endl;
return 0;
}