Q42 Maximum sum of consecutive subarrays

Maximum sum of consecutive subarrays

topic

HZ occasionally takes some professional questions to foole non-computer majors. After the test group meeting today, he spoke again: In ancient one-dimensional pattern recognition, it is often necessary to calculate the maximum sum of continuous subvectors. When the vectors are all positive numbers, the problem is solved well. However, if the vector contains negative numbers, should it contain a negative number and expect the positive number next to it to make up for it? For example: {6, -3, -2,7, -15,1,2,2}, the maximum sum of consecutive subvectors is 8 (starting from the 0th to the 3rd). Give an array and return the sum of its largest consecutive subsequences, will you be fooled by him? (The length of the subvector is at least 1)

Ideas

Idea 1

First, let's consider it with the idea of ​​dynamic programming.

Assuming that f (k) gives the largest continuous subsequence sum ending with the kth element of the array, then f (k) can be defined as follows, f (0) = arr [0]:

if (f(k-1)>0)
	f(k) = arr[k] + f(k-1)
else 
	f(k) = arr[k]

Based on f (k), loop through each element of the arr array and compare which element ends with the largest f (k).

But this method is very expensive. And there are repeated calculations.

Idea 2

Therefore, from low to top, recursion is not used, but f (0), f (1) are calculated in sequence, and the maximum value in this process is recorded.

  • Maintain a currentSum and maxSum

  • For an element, if the previous sum plus the current val is less than val, then it is better to start from the current. Otherwise, add this element.

  • Each time it is added, it is determined whether the maxsum needs to be updated.

achieve

//思路1的实现
class Solution {
public:
    int fSequenceSum(vector<int>& array, int index)
    {
        if(index==0)
            return array[index];
        int k = fSequenceSum(array, index-1);
        if(k <= 0)
            return array[index];
        else
            return k+array[index];        
    }
    int FindGreatestSumOfSubArray(vector<int> array) {
        if(array.empty()) return 0;
        //size 1 时
        int maxsum = array[0];
        for(int i=1; i<array.size(); ++i)
        {
            int tmp = fSequenceSum(array, i);
            maxsum = tmp>maxsum ? tmp : maxsum;           
        }
        return maxsum;    
    }
};
//思路2 的实现
class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> array) {
        if(array.empty()) return 0;
        int currentSum = array[0];
        int maxSum = currentSum;
        for(int i=1; i<array.size(); ++i)
        {
            int val = array[i];
            if((val + currentSum) < val)
                currentSum = val;
            else
                currentSum = val + currentSum;
            if(currentSum>maxSum)
                maxSum = currentSum;
        }
        return maxSum;
    }
};

Idea 3, divide and conquer

https://www.bilibili.com/video/av18586085?p=9

#include <limits.h>
class Solution {
public:

    //分治法
    /* 1.不断拆分,当前数组的最大子串和,等于 左边子串的最大子串和,右边子串的最大子串和 和 cross左右子串的最大值 中的 最大值
    https://www.bilibili.com/video/av18586085?p=9    */ 
    int maxSubArray(vector<int>& nums) {
        int result = INT_MIN;
        if(nums.empty()) return result;
        result = maxSubArrayCore(nums, 0, nums.size()-1);
        return result;
    }
    int maxSubArrayCore(vector<int>& nums, int left, int right)
    {
        if(left==right) return nums[left];
        int mid = (left+right) / 2;
        int leftMax = maxSubArrayCore(nums, left, mid);
        int rightMax = maxSubArrayCore(nums, mid+1, right);
        int crossMax = crossSubArrayMax(nums, left, right, mid);
        //返回 左边子串的最大子串和,右边子串的最大子串和 和 cross左右子串的最大值 中的 最大值
        return max(leftMax, max(rightMax, crossMax));
    }

    int crossSubArrayMax(vector<int>& nums, int left, int right, int mid)
    {
        //start from mid,  分别向两边扩展   <--mid-->
        int leftSum = nums[mid];
        int leftSumMax = leftSum; //[left, mid]
        for(int i=mid-1; i>=left; --i)
        {
            leftSum += nums[i];
            leftSumMax = max(leftSumMax, leftSum);
        }

        int rightSum = nums[mid+1];
        int rightSumMax = rightSum;//[mid+1, right]
        for(int i=mid+2; i<=right; ++i)
        {
            rightSum += nums[i];
            rightSumMax = max(rightSumMax, rightSum);
        }
        return leftSumMax + rightSumMax;
    }
};
Published 58 original articles · won 11 · 30,000+ views

Guess you like

Origin blog.csdn.net/mhywoniu/article/details/105606311