思路:贪心算法,每次碰到当前元素sum<0,直接更新sum的值,之前的值全部抛弃,但是问题是如果所有的输入都是负数,该怎么处理呢?
int maxSubArray(vector<int>& nums) {
int sum = 0;
int max_ = 0;
int minus = INT_MIN;
bool flag = true; //默认只有负数
for (int i : nums) {
if (i < 0&& flag) {
if(i > minus)
minus = i;
}
else {
flag = false;
sum += i;
sum = max(0, sum);
max_ = max(max_, sum);
}
}
return (flag==true?minus:max_);
}
注意看我操作(*^▽^*).
使用一个标记位flag来标记当前是否全部都是负数,如果遇到了正数,就更改flag的值,如果都是负数,取最大的那个负数.但是不能写成下面这样
if(i<0&&flag&&i>minus) { minus=i}
else{
...
}
不然比如我先遍历-2,再遍历-1,会进入到else中,导致最后输出的结果是0,而不是要求的最大负数!
第二方法:动态规划.
int maxSubArray(vector<int>& nums) {
int *dp =new int[nums.size()+1]; //dp[i]表示说以这个元素结尾的最大子序和,但是并不是从头到尾的最大
memset(dp, 0, sizeof(dp));
dp[0] = nums[0];
int much=nums[0];
for (int i = 1; i < nums.size(); ++i)
{
dp[i] = max(nums[i], dp[i-1] + nums[i]); //选择加入这个nums[i]或者重新选择一个nums[i],舍弃之前选择的元素
much = max(dp[i], much);
}
return much;
}
借助于贪心思想,我们不断选取当前元素和到之前i-1项的最大dp值中的最大值.需要说明的是,我们需要记录max(dp[i]).
因为dp[i]表示的是说不论如何nums[i]一定会被选取的规则,所以我们并不是说从0~n-1项的最大子序和,而是说包含了当前元素的最大子序和!