问题描述
最长子序和:
给定一个整数数组 nums
,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
我们用Leetcode中的题目为例子,URL传送-->https://leetcode-cn.com/problems/maximum-subarray/
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
解释问题
可能有些小伙伴刚入门,会有点疑惑, 什么是最长子序列呢?(大佬勿喷)
首先,我们先来理解,在这个题目中, 什么是子序列:
在这个例题中,
如果我们从-2开始, 那么子序列可以为:{-2}, {-2,1},{2,-1,-3},{-2,1,-3,4}, ... , {-2,1,-3,4,-1,2,1,-5,4}
如果我们从1开始,那么子序列可以为{1},{1,-3},{1,-3,4}, ... , {1,-3,4,-1,2,1,-5,4}
如果我们从-3开始,那么子序列可以为{-3},{-3, 4}, ... , {-3,4,-1,2,1,-5,4}
... ...
同理, 到如果从最后一个数, 4开始,那么子序列为{4}
理解了子序列后,那么可以很直观的直到, 最长子序列和,就是我们穷举出的这么多子序列中,他们的和最大的一个子序列。
参考例子
解法一:
首先我们先用暴力的方法来破解, O(N^2)
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int length = nums.size();
if(length == 0) return 0;
int max = nums[0];
int sum=0;
for(int i=0; i<length; i++){
sum=0;
for(int j=i; j<length; j++){
sum += nums[j]; //统计每个子序列的和
if( sum > max ) //判断最大的子序列和,并保存
max=sum;
}
}
return max;
}
};
解法二:O(N)
由于子序列的范围为0 ~ length-1, 所以,我们可以推算出子序列的最大和也是在这个范围当中。 然后我们假设这个序列的第一个数为最大值max,此时游标i为结尾所处的子序列和为here, 然后我们从第二位开始遍历, 比较此时序列和是否大于0, 如果大于0, 则遍历的序列和与此时所处i的数组相加,如果小于等于0,那么我们将此时i处的数组的值,赋值为以i为结尾的最大的子序列和,用这样的方式遍历从1 ~ length-1,就可以找出最大子序列和, 在每次处理完子序列和的同时呢, 我们要判断当前最大的子序列,并保存下来。
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int length = nums.size();
if(length == 0) return 0;
int max = nums[0];
int here = nums[0];
for(int i=1; i<length; i++){
if(here>0)
here += nums[i];
else
here = nums[i];
if(max<here)
max = here;
}
return max;
}
};