1.描述
给定一个整数数组,找到一个具有最大和的子数组,返回其最大和。
注意事项
子数组最少包含一个数
样例
给出数组[−2,2,−3,4,−1,2,1,−5,3]
,符合要求的子数组为[4,−1,2,1]
,其最大和为6
2.分析
找到一个最大和的子数组,注意所求子数组中的数是连续的,并不能从数组中任意选取元素相加最大和。
3.代码
class Solution {
public:
/*
* @param nums: A list of integers
* @return: A integer indicate the sum of max subarray
*/
int maxSubArray(vector<int> &nums) {
// write your code here
int n=nums.size();
//int i,j,k,h;
int sum=0;
//for(i=0;i<n&&nums[i]<0;i++);//找到nums中的第一个非负整数
//for(j=n-1;j<n&&nums[j]<0;j--);//找到nums中的最后一个非负整数
int k=0;
int max=nums[k];
while(k<n)
{
sum+=nums[k];
if(sum>max) max=sum;
if(sum<0) sum=0;
k++;
}
return max;
}
};
4.总结
此题初看十分简单,找到最大和,只需要把所有的正数加起来就可以。我最初的想法是通过开头注释掉的两句找到数组中的第一个正数和最后一个正数,i指向第一个正数,j指向最后一个正数,然后把i和j之间的数加起来即为最大和,这样掐头去尾数组前后的负数进而简化运算。然而缺点是当数组中全为负数时i和j找不到对应的位置分别指向队尾和队头,自然找不到对应的元素再加和。
实际上输出最大和根据贪心算法的思想不需要找到是哪一段,只要找到最大的和即可(当然要保证是连续的子数组的和)。假设数组的前两个数加和为负数,再往后加时如果带上这两个数只能让数变小,因此子数组一定不包括这两个数,由此我们可以判断当连续的子数组加和后出现负数说明到目前这个数为止前面的数加起来只能提供“负面影响”,要找更大的和后面的数要从头开始加和。
因此不妨选定第一个元素为max,之后对数组的元素进行加和,若和变大则更新最大和max。注意,若和变小此时只能说明加到了一个负数,但不代表后面的数也是负数,因此继续加和,直到这个和变成负数,根据之前的分析,说明走到这一步已经变为“负面影响”。从当前位置开始加和清零,对后面的元素再进行加和运算,若加和超过max则更新最大和,加和为负数则清空,加和即使变小还是正数说明这孩子还有希望,继续加和,直到数组结束为止。