描述:输入一个长度为n的整型数组array,数组中的一个或连续多个整数组成一个子数组,找到一个具有最大和的连续子数组。
1.子数组是连续的,比如[1,3,5,7,9]的子数组有[1,3],[3,5,7]等等,但是[1,3,7]不是子数组;
2.如果存在多个最大和的连续子数组,那么返回其中长度最长的,该题数据保证这个最长的只存在一个;
3.该题定义的子数组的最小长度为1,不存在为空的子数组,即不存在[]是某个数组的子数组;
4.返回的数组不计入空间复杂度计算;
数据范围:1<=n<=105,−100<=a[i]<=100。
要求:时间复杂度O(n),空间复杂度O(n)。
进阶:时间复杂度O(n),空间复杂度O(1)。
输入:[1,-2,3,10,-4,7,2,-5]
返回值:[3,10,-4,7,2]
说明:经分析可知,输入数组的子数组[3,10,-4,7,2]可以求得最大和为18,故返回[3,10,-4,7,2]
输入:[1]
返回值:[1]
输入:[1,2,-3,4,-1,1,-3,2]
返回值:[1,2,-3,4,-1,1]
说明:经分析可知,最大子数组的和为4,有[4],[4,-1,1],[1,2,-3,4],[1,2,-3,4,-1,1],故返回其中长度最长的[1,2,-3,4,-1,1]
输入:[-2,-1]
返回值:[-1]
说明:子数组最小长度为1,故返回[-1]
连续子数组的最大和(二):最直观的想法是,相对于(一)其区别在于要记录区间起始位置和结束位置,并且相同最大和的情况下返回长度最长的数组,而(一)中我们使用的是dp[i]表示以下标i为结尾的连续子数组的最大和,其递推公式为dp[i]= max(dp[i-1]+array[i],array[i])。那么怎么办呢?我们可以使用start和end分别表示当前区间起始位置和结束位置,初始均为0,maxs和maxe分别表示最大和区间起始位置和结束位置,初始也均为0,dp[0]初始化为第一个元素值,使用maxres表示最大和,初始为第一个元素值。与(一)的区别在于,每次循环遍历i时记录结束位置end为i,使用公式更新完dp[i]后,如果dp[i-1]+array[i]小于array[i],那么就更新起始位置为i,同时当dp[i]大于maxres或者dp[i]等于maxres且区间长度更大时,则更新最长区间以及最大值。最后将[maxs,maxe]区间的数值加入到结果数组中即可。
vector FindGreatestSumOfSubArray(vector& array)
{
int n=array.size();
// dp[i]表示已i为结尾的连续子数组 dp[i]=max(dp[i-1]+array[i],array[i])
vector dp(n,0);
// 此处要求有多个的话返回最长的 故要记录起始和结束
int start=0,end=0; //最初区间为第一个元素
dp[0]=array[0];
int maxres=array[0]; //记录最大区间和为第一个元素
int maxs=0,maxe=0; //最初区间为第一个元素
for(int i=1;imaxres||(dp[i]==maxres && end-start+1 > maxe-maxs+1))
{
maxe=end;
maxs=start;
maxres=dp[i];
}
}
vector res;
for(int i=maxs;i<=maxe;i++)
res.push_back(array[i]);
return res;
}