[Dynamic Programming Question 9] Maximum subarray sum III && Maximum sum of circular subarrays

Maximum subarray sum

Link: 53. Maximum sum of subarrays

Given an integer array nums, please find a continuous subarray with the maximum sum (the subarray contains at least one element) and return its maximum sum.

A subarray is a contiguous portion of an array.

Example 1:
Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6
Explanation: The sum of consecutive subarrays [4,-1,2,1] The maximum is 6.

Example 2:
Input: nums = [1]
Output: 1

Example 3:
Input: nums = [5,4,-1,7,8]
Output: 23

1. Status indication *

We define a state representation:
dp[i] means: the maximum sum of the sums in "all sub-arrays" ending with the element at position i.

2. State transition equation

All possibilities of dp[i] can be divided into the following two types:

  1. i. The length of the subarray is 1: at this time dp[i] = nums[i];
  2. ii. The length of the subarray is greater than 1: At this time, dp[i] should be equal to the maximum value of the sum of "all subarrays" ending with i - 1 plus nums[i], which is dp[i - 1] + nums[i].

Since what we want is the "maximum value", it should be the maximum value in the two situations, so the transfer equation can be obtained:

dp[i] = max(nums[i], dp[i - 1] + nums[i]) 

3. Initialization

You can add an "auxiliary node" at the front to help us initialize. There are two points to pay attention to when using this technique:
i. The value in the auxiliary node must "ensure that subsequent filling in the form is correct";
ii. "The mapping relationship of subscripts".
In this question, just add a grid at the front and let dp[0] = 0. There is a risk of "overflow" during the process. Here INF is halved to 0x3f3f3f3f, which is small enough)

4. The order of filling in the form.
According to the "State Transition Process", the order of filling in the form is "from left to right"

5. Return value
The status is expressed as the maximum value of "all subarrays ending with i", but we are not sure about the end of the maximum subarray sum.
Therefore we need to return the maximum value in the entire dp table.

Code:

  int maxSubArray(vector<int>& nums) {
    
    
        int n=nums.size();
        if(n==1) return nums[0];
        vector<int> dp(n);
        dp[0]=nums[0];

        int Max=nums[0];
        for(int i=1;i<n;i++)
        {
    
    
            dp[i]=max(dp[i-1]+nums[i],nums[i]);
            Max=max(Max,dp[i]);
        }
        return Max;
    }

Maximum sum of circular subarrays

Link: 918. Maximum sum of circular subarrays

Given a circular integer array nums of length n, return the maximum possible sum of non-empty subarrays of nums.

A circular array means that the end of the array will be connected to the beginning to form a ring. Formally, the next element of nums[i] is nums[(i + 1) % n] and the previous element of nums[i] is nums[(i - 1 + n) % n].

The subarray may contain each element in the fixed buffer nums at most once. Formally, for the subarrays nums[i], nums[i + 1], …, nums[j], there is no i <= k1, k2 <= j where k1 % n == k2 % n.

Example 1:
Input: nums = [1,-2,3,-2]
Output: 3
Explanation: Get the maximum sum 3 from subarray [3]

Example 2:
Input: nums = [5,-3,5]
Output: 10
Explanation: Get the maximum sum 5 + 5 = 10 from the subarray [5,5]

Example 3:
Input: nums = [3,-2,2,-3]
Output: 3
Explanation: The maximum sum 3 can be obtained from both subarrays [3] and [3,-2,2]

Algorithm idea:

The difference between this question and "Maximum subarray sum" is that when considering the problem, you must not only analyze the " continuous area within the array ", but also consider the part of the " array connected from end to end ". The possible results are divided into the following two situations:

  1. i. The result is inside the array, including the entire array;
  2. ii. The result is in the contiguous part of the array.

Among them, for the first case, we only need to follow the "maximum subarray sum" method to get the result, which is recorded as fmax.

For the second situation, we can analyze:

  1. i. If the part connected from the beginning to the end of the array is the largest array sum, then there will be an empty part in the middle of the array;
  2. ii. Because the sum of the array is constant, the sum of the consecutive parts in the middle must be the smallest;

Therefore, we can draw a conclusion that the maximum sum in the second case should be equal to sum - gmin, where gmin represents the "minimum subarray sum" in the array.
The maximum value in the two situations is the result we want.

However, since the array may all contain negative numbers, the result in the first case is the maximum value in the array (a negative number). In the second case, gmin == sum, the result will be 0 . If you directly find the maximum value of the two, it will be 0. But the actual result should be the maximum value in the array. For this situation, we need to make a special judgment.

1. Status indication *

g[i] means: the minimum value of the sum of "all subarrays" ending with i.
f[i] means: the maximum value of the sum of "all subarrays" ending with i. (See the previous question for details on finding the maximum value)

2. State transition equation

All possibilities of dp[i] can be divided into the following two types:

  1. i. The length of the subarray is 1: at this time g[i] = nums[i];
  2. ii. The length of the subarray is greater than 1: At this time, g[i] should be equal to the minimum value of the sum of "all subarrays" ending with i - 1 plus nums[i], that is, g[i - 1] + nums[i] .

Since what we want is the "minimum value", it should be the minimum value in the two situations, so the transfer equation can be obtained:

g[i] = min(nums[i], g[i - 1] + nums[i]) 

3. Initialization

We can add an auxiliary node at the front to help us initialize. There are two points to note when using this technique:

  1. i. The value in the auxiliary node must ensure that the subsequent form filling is correct;
  2. ii. The mapping relationship of subscripts.

In this question, just add a grid at the front and let g[0] = 0.

4. The order of filling in the form.
According to the state transfer process, the order of filling in the form is "from left to right".

5. Return value
a. First find the maximum value in the f table -> fmax;
b. Find the minimum value in the g table -> gmin;
c. Count the sum of all elements -> sum;
b. Return sum == gmin ? fmax : max(fmax, sum - gmin)

Code:

 int maxSubarraySumCircular(vector<int>& nums) {
    
    
        int n=nums.size();

        vector<int> f(n),g(n);
        f[0]=g[0]=nums[0];

        int gmin=nums[0];
        int fmax=gmin;
        for(int i=1;i<n;i++)
        {
    
    
            f[i]=max(f[i-1]+nums[i],nums[i]);
            fmax=max(fmax,f[i]);
            g[i]=min(g[i-1]+nums[i],nums[i]);
            gmin=min(gmin,g[i]);
        }

        int sum=0;
        for(int i=0;i<n;i++) sum+=nums[i];
        int ret=sum-gmin;
        if(ret==0) return fmax;

        return fmax>ret?fmax:ret;
    }

Guess you like

Origin blog.csdn.net/m0_64579278/article/details/132631975