题解 | #连续子数组的最大和(二)#
连续子数组的最大和(二)
https://www.nowcoder.com/practice/11662ff51a714bbd8de809a89c481e21
class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param array int整型vector * @return int整型vector */ vector<int> FindGreatestSumOfSubArray(vector<int>& array) { if(array.size() <= 1) return array; vector<int> dp(array.size(),0); int maxNumber = array[0]; dp[0] = array[0]; int start = 0; int end = 0; int rstart = 0; int rend = 0; for(int i = 1;i < array.size();i ++){ //一直扩张大区间 end ++; //转移方程 dp[i] = max(dp[i - 1] + array[i],array[i]); //Start将当前元素与之前数组分割开来 if(array[i] > dp[i - 1] + array[i]){ start = end; } //检测区间内出现更大的值时,记录最大值,同时更新返回区间与检测区间相同 if(dp[i] > maxNumber){ maxNumber = dp[i]; rstart = start; rend = end; } //检测区间内再次出现最大值,若长度比现在的返回区间要长,则更新返回区间 else if(dp[i] == maxNumber && (end - start) > (rend - rstart)){ rstart = start; rend = end; } } //返回小区间即可 vector<int> res; for(int i = rstart;i <= rend;i ++) { res.push_back(array[i]); } return res; } };
使用一个start,end来确定一个检测区间,一旦有元素值大于前面检测区的最大值加上它自己的话,拿么就更新检测区到这个元素,将这个元素与前面所有元素分割开来,因为要想获得最大值,这个元素不可能和前面的元素组成数组。总的来说就是这个元素嫌前面相邻的队友,自己单干都比与他们合作的数值大。
为了弄明白这道题目:
首先,要想明白一个问题:
假设有一个检测区间内的局部最大值,其下标为i,那么i一定小于等于end(注意元素值可能为正可能为负)。并且当前检测区域的局部最大长度子数组一定为start到i。 我们可以把这个区间叫做局部最大区间,这个最大值叫做局部最大值(还有一个全局最大值,即问题一求的)
接下来:
由于end一直向后移动,那么局部最大值肯能会更新。那么我们在局部最大值更新时让它与全局最大值作比较,有三种情况:
- 若它比全局最大值小,就不用管。
- 若它比全局最大值大,则这个局部最大区间就是现在的全局最大区间了,那么把返回区间等于上这个全局最大区间就行了。
- 若它与全局最大值相等,那就再比较局部最大区间与全局最大区间的长度,那个长,那个就是全局最大区间(题目要求最长子数组)。
所以:
使用一个rstart,rend来确定一个返回区间:
- 一旦在检测区间内发现了最大值,就把自己更新到与检测区间相同。
- 因为要求最大长度,所以一旦在检测区间发现了等于当前最大值的值,并且检测区间的长度要大于当前返回区间的长度,则更新返回区间与检测区间相同。
新手学习中,记录与分享我刷题的一些想法。大家请请多指正。