例题描述
一个数组有 N
个元素,求连续子数组的最大和。 例如:[-1,2,1]
,和最大的连续子数组为[2,1]
,其和为 3
。
-
输入描述:
输入为两行。
第一行一个整数n
(1 <= n <= 100000),表示一共有n
个元素
第二行为n
个数,即每个元素,每个整数都在32
位int
范围内。以空格分隔。 -
输出描述:
所有连续子数组中和最大的值。
示例1:
- 输入:
3 -1 2 1
- 输出:
3
解题思路
本题是一个经典的动态规划问题,简称dp
问题,本题题意很简单,就是求哪一段的子数组的和最大。
假设sum[i-1]
是以数组中第nums[i-1]
为最后一个元素的一段子数组最大和;
sum[i]
是以数组中第nums[i]
为最后一个元素的一段子数组最大和;
那么sum[i]
= max(sum[i-1], 0)
+ nums[i]
。
理解了这个,下面代码中用sum1
表示sum[i-1]
,sum2
表示sum[i]
;
如果计算出更大的子数组和则保存到result
中。
如果sum[i]
及sum2
都小于0
了,则置为0
,因为它加上数组下一个数,不会计算出更大的子数组和。
代码实现一
#include <iostream>
#include<vector>
using namespace std;
int main(){
int size;
cin >> size;
vector<int> nums(size);
for(size_t i = 0; i < size; ++i)
cin >> nums[i];
int result = nums[0];
int sum1 = 0, sum2 = 0;
for (int i = 0; i < nums.size(); i++){
// 计算到num[i]的子数组的最大和
sum2 = sum1 >= 0 ? sum1+nums[i] : nums[i];
if(sum2 > result)
result = sum2;
if(sum2 < 0)
sum2 = 0;
sum1 = sum2;
}
cout << result << endl;
return 0;
}
代码实现二
#include <iostream>
#include <vector>
using namespace std;
int main(){
int N;
cin >> N;
vector<int> v(N);
for(int i = 0;i < N;++i)
cin >> v[i];
// F(i)初始化
int Max = v[0];
// maxsum初始化
int maxSum = v[0];
for(int i = 1;i < N;++i){
// 状态转移方程:F(i) = max(F(i-1) + array[i],array[i])
Max = (Max >= 0 ? Max + v[i] : v[i]);
// maxsum = max(maxsum,F(i))
maxSum = max(Max,maxSum);
}
cout << maxSum << endl;
}
链接:https://www.nowcoder.com/practice/5a304c109a544aef9b583dce23f5f5db?tpId=85&&tqId=29858&rp=1&ru=/activity/oj&qru=/ta/2017test/question-ranking