Maximum subarray sum (maximum sum of continuous subarrays) -- Fundamentals

Posted by ihw13 on Tue, 28 Dec 2021 15:05:33 +0100

Maximum subarray sum (dynamic programming, divide and conquer):

The solution of this problem is only for personal understanding. If there are other ideas or solutions, welcome to explore!
Buckle link: Maximum sum of consecutive subarrays

Title:

Enter an integer array. One or more consecutive integers in the array form a sub array. Find the maximum value of the sum of all subarrays.

Example:

input: nums = [-2,1,-3,4,-1,2,1,-5,4]
output: 6
 explain: Continuous subarray [4,-1,2,1] The sum of is 6.

analysis:

At first glance, this problem is a problem to investigate dynamic programming (of course, it can also be divided into other algorithms, but here the optimal solution is dynamic programming, so the following analysis is explained by dynamic analysis).

We first analyze the problem. The problem requires that you input a string of consecutive integers to form a sub array and return the maximum sum of consecutive sub arrays. As can be seen from the example, when the input is [- 2,1, - 3,4, - 1,2,1, - 5,4], the maximum sum of continuous subarrays is 6, and the subarray is [4, - 1,2,1]. It is required to output only the maximum sum of continuous sub arrays without outputting the corresponding sub arrays.

In dynamic planning, we should find ways to achieve the following three key objectives:

  1. Establish the state transition equation
  2. Cache and reuse past results
  3. From small to large in order

Here, we find the state transition equation: dp[i] = max(dp[i-1] + nums[i], nums[i]),
Where dp[i] represents the maximum value of the subarray when the index I is the end point.

Then the initial state: DP [0] = num [0]

But for this problem, we don't need to cache all the results. We only need to cache the last maximum value, so we don't need to open up a new array, just create a new variable pre to store the last result.

You can start writing code:

code:

First look at the above analysis! Understand and think for yourself. Don't look at the code in a hurry!

Dynamic planning:

Time complexity: O(n); Space complexity: O(1)

 public int maxSubArray(int[] nums) {
       int pre = 0, result = nums[0];
        for (int i = 0; i < nums.length; i++) {
            pre = Math.max(pre + nums[i], nums[i]);//Compare the larger value of num[i] and num[i] + the sum of the first few digits in the array to obtain the larger value of the sum of the array at the current I-bit
            result = Math.max(result, pre);//Compare the larger value of the sum with the maximum value of the sum and store it in the current maximum value
        }
        return result;

    }

Finally, the operating efficiency obtained in the force buckle:

Here, I add the divide and conquer method and another method I wrote myself:

Divide and conquer (specific explanations include:

Time complexity: O(nlogn); Space complexity: O(1)
The maximum sum of continuous subarrays is mainly obtained from the maximum sum of elements in the following three molecular intervals:
Left subinterval [left, mid]
Right sub interval [left, mid]
Cross left and right intervals, i.e. num [mid] and num [mid + 1] will be selected

public int maxSubArray(int[] nums) {
        return maxSubArrayPart(nums, 0, nums.length-1);
    }
    
public int maxSubArrayPart(int[] nums, int left, int right){
        if (left == right) return nums[left];//Find the last bit left and return to itself
        int mid = (left+right)/2;//Find the median two points
        return Math.max(maxSubArrayPart(nums,left,mid),Math.max(maxSubArrayPart(nums,mid+1,right),maxSubArrayAll(nums,left,mid,right)));
    }
    
    //Calculation span left and right sections
public int maxSubArrayAll(int[] nums, int left, int mid, int right){
        int leftSum = Integer.MIN_VALUE;
        int sum = 0;
        //Left interval maximum
        for (int i = mid; i >=left; i--){
            sum+=nums[i];
            leftSum = Math.max(sum,leftSum);
        }
        
        sum = 0;
        //Maximum value of right interval
        int rightSum=Integer.MIN_VALUE;
        for(int i = mid + 1; i <=right;i++){
            sum+=nums[i];
            rightSum = Math.max(rightSum, sum);
        }
        return leftSum+rightSum;
    }

Operating efficiency obtained in force buckle:

My own alternative:

public int maxSubArray(int[] nums) {
        int startIndex = 0;//The starting subscript of the record subarray
        int endIndex = 0;//End subscript of record subarray
        int sum = 0;//Storage and

        int temp = 0;//Temporary sum to store the sum of the current array
        int tempStartIndex = -1;//Temporary start subscript

        for (int i = 0 ; i < nums.length ; i++){
            if (temp < 0)   //If temp < 0; You need to reassign temp
            {
                temp = nums[i];    //Reassign temp
                tempStartIndex = i;  //Temporarily record the new starting position of the sub array (and maximum) (depending on whether the subsequent sum and temp are exchanged)
            }
            else
            {
                temp += nums[i];   //temp >= 0; Calculate the current temporary maximum sum
            }

            if (sum < temp) //If sum < temp; Indicates that the subarray sum at this time is greater than the previous subarray sum
            {
                sum = temp; //Assign temp to sum
                startIndex = tempStartIndex; //Save the temporary start index saved before, and record the start index of the sub array
                endIndex = i;   //End subscript of record subarray
            }
        }
        if (endIndex - startIndex == 0){
            return Arrays.stream(nums).max().getAsInt();//The maximum value is found when all are negative
        }
        return sum;
    }

Operating efficiency obtained in force buckle:

Topics: Java Algorithm leetcode Dynamic Programming divide and conquer