连续子数组的最大和(二):最直观的想法是,相对于(一)其区别在于要记录区间起始位置和结束位置,并且相同最大和的情况下返回长度最长的数组,而(一)中我们使用的是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<int> FindGreatestSumOfSubArray(vector<int>& array) { int n=array.size(); // dp[i]表示已i为结尾的连续子数组 dp[i]=max(dp[i-1]+array[i],array[i]) vector<int> 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;i<n;i++) { end=i; //结束位置为i dp[i]=max(dp[i-1]+array[i],array[i]); // 更新起始位置 if(dp[i-1]+array[i]<array[i]) start=i; // 更新最长区间以及最大值 if(dp[i]>maxres||(dp[i]==maxres && end-start+1 > maxe-maxs+1)) { maxe=end; maxs=start; maxres=dp[i]; } } vector<int> res; for(int i=maxs;i<=maxe;i++) res.push_back(array[i]); return res; }