写在前面
最近开始学C++。之前尝试在博客园写文章,结果莫名其妙没有发送出来,突然就颓了。断断续续做了几天题目,觉得如果零零散散的话对学习还是没有什么帮助。于是决定在CSDN来写写试试看。引用我的一位同学po在朋友圈的话:多做一些以年为单位的事情吧。
题目说明
The maximum sum subarray problem consists in finding the maximum sum of a contiguous subsequence in an array or list of integers:
maxSequence({-2, 1, -3, 4, -1, 2, 1, -5, 4});
//should be 6: {4, -1, 2, 1}
Easy case is when the list is made up of only positive numbers and the maximum sum is the sum of the whole array. If the list is made up of only negative numbers, return 0 instead.
Empty list is considered to have zero greatest sum. Note that the empty list or array is also a valid sublist/subarray.
我的想法
刚开始拿到没啥思路,想着用暴力求解的方法,但是并没有很好的效果。去查了一下资料发现别人说是动态规划问题。我???俺啥也不懂,怎么办?
静下心来分析一下。问题需要我们求解的是一个数组的最大子数组和。对于正负数混合的情况,若arr[i] - arr[j] < 0且arr[j+1]>0
,那么对子数组arr[i]~arr[j+1]
,它的子数组的和的最大值必定为arr[j+1]
。
因此,我们可以通过for循环遍历数组。采用maxCurr
和Sum
两个辅助变量。Sum
用来表示当前循环下的子序列求和值,maxCurr
用来表示循环后最大的和值。最终取二者的最大值用于返回。
在遍历过程中,若arr[i]>0
,则直接取出相加求和;若arr[i]<0
,则首先得到当前情况下的maxCurr
,再去判断Sum+arr[i]>0?
来决定是否要继续求和。若结果小于0,则该段Sum必不可能为最大值,将Sum重置为0,继续寻找子序列。循环结束时若数列全为负数,则返回0;
我的代码实现
int maxSequence(const vector<int>& arr){
//根据题目条件,若为空容器,返回0;只有一个元素时,也进行相应的判断
int len = arr.size();
if(len == 0)
return 0;
if(len == 1)
return arr[0]>=0? arr[0]:0;
//辅助变量初始化赋值
//与第一个元素比较
int maxCurr = arr[0]>0? arr[0]:0;
int Sum = arr[0]>0? arr[0]:0;
//循环开始
for(int i=1; i<len ; i++)
{
//元素>0时,直接相加
if(arr[i]>0)
Sum += arr[i];
//元素<0时,需要进行判断
//更新一次maxCurr的值
//若相加后Sum值<0,则必不可能为最大和
else
{
maxCurr = maxCurr > Sum? maxCurr : Sum;
Sum = Sum + arr[i] > 0 ? Sum + arr[i] : 0;
}
}
return maxCurr >= Sum? maxCurr : Sum;
}
大神代码实现(供参考)
#include <vector>
using namespace std;
int maxSequence(const vector<int>& arr) noexcept {
int max = 0, local = 0;
for (auto x : arr) {
local = std::max(0, x + local);
max = std::max(max, local);
}
return max;
}
//From User:7097511