[LeetCode] Jianzhi Offer 42. The maximum sum of continuous subarrays p218 -- Java Version

Link to the topic : https://leetcode.cn/problems/lian-xu-zi-shu-zu-de-zui-da-he-lcof/

1. Topic introduction (42. Maximum sum of consecutive subarrays)

Input an integer array, one or more consecutive integers in the array form a sub-array. Find the maximum of the sum of all subarrays.

The required time complexity is O(n).

[Test case]:
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] is the largest, which is 6.

[Conditions]:

Tips :

  • 1 <= arr.length <= 10^5
  • -100 <= arr[i] <= 100

【Related Topics】:

Note : This question is the same as the main site [LeetCode] No.53. The largest sub-array sum – Java Version .

2. Solution

2.1 Enumeration – O(n 2 )

Time complexity O(n 2 ), space complexity O(1)

[ Problem-solving ideas ]:
Unresolved when things happen, violent enumeration, the most direct method, 枚举数组的所有子数组and find their sum. But I don’t know if it’s because I’ve been doing a lot of hard work recently. What I thought at the beginning was 1. Separate all sub-arrays first; 2. Traverse and compare all sub-arrays to find the largest. 所有符合条件的子数组It is more reasonable to use this method if the question requires return . If it is just like this question, the return is only the maximum value, which is true and unnecessary.
...
Implementation strategy】:

  1. Define a double loop to loop through the possibility of each sub-array;
  2. Define the current cumulative sum variable sumand the maximum sum maxSum. Once the current cumulative sum is found to be greater than the maximum sum, modify the maximum sum to the cumulative sum;
  3. The loop ends and the result is returned.
class Solution {
    
    
    // Soulution1:枚举所有子数组和
    public int maxSubArray(int[] nums) {
    
    
        // 定义变量 n 记录数组长度
        int n = nums.length;
        // 定义变量 maxSum 记录最大子数组和
        int maxSum = Integer.MIN_VALUE;
        // 双重循环,依次遍历所有可能的子数组
        for (int i = 0; i < n; i++)
        {
    
    
            int sum = 0;
            for (int j = i; j < n; j++)
            {
    
    
                sum = sum + nums[j];
                // 如果当前子数组的和大于 maxSum,则让其成为最大
                if (sum > maxSum)
                {
    
    
                    maxSum = sum;
                }
            }
        }
        // 最后返回结果
        return maxSum;
    }
}

insert image description here

2.2 Example to analyze the law of arrays (original solution 1) -- O(n)

Time complexity O(n), space complexity O(1)

[ Problem solving ideas ]:
Try to accumulate each number in the example array one by one from the beginning to the end , and initialize the sum to 0. The first step is to add the first number 1, and the sum is 1 at this time. Add the number -2 to the second part, and the sum becomes -1. The third step is to add the number 3. We noticed that since the previous accumulated sum is -1, which is less than 0, then if we add -1 to 3, the resulting sum is 2, which is smaller than 3 itself. Therefore, we don't consider subarrays starting from the first number, and the accumulated sums are also discarded.
By way of example, we can find the following rules:

  1. Start traversing and accumulating from the first element, if the accumulative sum is less than or equal to 0 (when a negative number is encountered, the accumulative sum is reduced), it means that the sub-array at this time must not be the largest, and it can be discarded;
  2. After discarding the previous cumulative sum, start again with the current value traversed until the traversal ends to obtain the maximum sum.

...
Implementation strategy】:

  1. As shown in the idea of ​​solving the problem, one traversal, when the current accumulated sum sumis less than or equal to 0, discard the previous accumulated sum and only assign it to the current number;
  2. If the cumulative sum is greater than 0, let it continue to accumulate;
  3. In the process of traversal, once it is found that the current cumulative sum is greater than the maximum sum maxSum, the value of the maximum sum is modified to the current cumulative sum.
class Solution {
    
    
    // Soulution2:一次遍历
    public int maxSubArray(int[] nums) {
    
    
        // 判断无效输入
        if (nums.length <= 0) return -1;
        // 定义变量 n 记录数组长度
        int n = nums.length;
        // 定义累加和 sum 与 最大和 maxSum
        int sum = 0;
        int maxSum = Integer.MIN_VALUE;
        // 开始循环
        for (int i = 0; i < n; i++){
    
    
            // 如果当前 累加和 小于等于0,丢弃该值,重新开始
            if (sum <= 0) sum = nums[i];
            else sum += nums[i];
            // 如果在循环的过程中出现了更大值,则修改最大和
            if (sum > maxSum) maxSum = sum;
        }
        return maxSum;
    }
}

insert image description here

2.3 Dynamic programming (original solution 2) -- O(n)

Time complexity O(n), space complexity O(1)
insert image description here

[ Problem-solving ideas ]:
About when to use DP?

  • First of all, you have to understand 回溯法, after all, it DPis the origin of , after you are familiar with backtracking, you find that this question seems to be able to use backtracking, or you find that you want to traverse it to give an answer, but the answer does not require all the satisfied The solutions are all listed, but only a few solutions need to be given, which can generally be considered at this time DP.

...
as shown in the formula above:

  • We can use the function f(i)to represent ithe maximum sum of the sub-arrays ending with the number, then we need to find out max[f(i)], among them 0 <= i < n.;
  • i-1When the sum of the numbers of the subarray ending with the th number is less than 0, add this negative number to the th inumber, and the result will be smaller than the ith number itself, so in this case the isubarray ending with the th number The array is ithe number itself;
  • i-1If the sum of the numbers in the subarray ending with the number is greater than 0, addingi to the number gives the sum of all the numbers in the subarray ending with the number.i

...
[ Implementation strategy ]:
Dynamic programming belongs to the value of the latter state depending on the previous state, here, it is dp[i]only dp[i-1]related to . In this question, the idea of ​​dynamic programming is used to solve the problem. The code is almost the same as 2.2. In fact, it is to find the relationship, but the difficulty lies in how to find the recursive relationship from the previous .

class Solution {
    
    
    public int maxSubArray(int[] nums) {
    
    
        int count = nums.length;
        int sum = nums[0],dp=nums[0];
        for(int i = 1; i < count; i++)
        {
    
    
            if(dp > 0) dp += nums[i];
            else dp = nums[i];
            sum = Math.max(sum,dp);
        }
        return sum;
    }
}

insert image description here

3. References

[1] Interview question 42. The maximum sum of continuous sub-arrays (dynamic programming, clear diagram)
[2] If you think of dp at the first time, write it in 1 minute
[3] Introduction to dynamic programming algorithm

Guess you like

Origin blog.csdn.net/qq_41071754/article/details/129875105