The "Maximum Subsequence Sum" of the Dynamic Programming Series

53. Maximum suborder sum

Given an integer array nums, find a continuous sub-array with the largest sum (the sub-array contains at least one element), and return the largest sum.

This problem cannot be done with a sliding window, because the array contains complex numbers, so the size of the window cannot be determined.

The sliding window is used in the sequence of continuous positive numbers where the sum is S

The idea can be seen in the official problem explanation, the explanation is very clear, so I won’t repeat it here...
You can also refer to labuladong

Method one: dynamic programming

class Solution {
    
    
    public int maxSubArray(int[] nums) {
    
    
        int tmp = 0;  // tmp 表示以nums[i]为结尾时的最大子序和,我们的目的是求得所有的,然后找出最大的
        int res = nums[0];  // res表示到目前nums[i]为止,之前以 nums[k],0≤k≤i 为结尾的所有最大子序和的最大值。
        for(int each : nums){
    
    
            tmp = Math.max(tmp + each, each);
            res = Math.max(res, tmp);
        }
        return res;
    }
}

Time complexity: O(n)

Space complexity: O(1)

Method two: divide and conquer

class Solution {
    
    
    public class Status {
    
    
        public int lSum, rSum, mSum, iSum;

        public Status(int lSum, int rSum, int mSum, int iSum) {
    
    
            this.lSum = lSum;
            this.rSum = rSum;
            this.mSum = mSum;
            this.iSum = iSum;
        }
    }

    public int maxSubArray(int[] nums) {
    
    
        return getInfo(nums, 0, nums.length - 1).mSum;
    }

    public Status getInfo(int[] a, int l, int r) {
    
    
        if (l == r) {
    
    
            return new Status(a[l], a[l], a[l], a[l]);
        }
        int m = (l + r) >> 1;
        Status lSub = getInfo(a, l, m);
        Status rSub = getInfo(a, m + 1, r);
        return pushUp(lSub, rSub);
    }

    public Status pushUp(Status l, Status r) {
    
    
        int iSum = l.iSum + r.iSum;
        int lSum = Math.max(l.lSum, l.iSum + r.lSum);
        int rSum = Math.max(r.rSum, r.iSum + l.rSum);
        int mSum = Math.max(Math.max(l.mSum, r.mSum), l.rSum + r.lSum);
        return new Status(lSum, rSum, mSum, iSum);
    }
}

Time complexity: Time complexity is O(n)
Space complexity: Recursion will use O(logn) stack space, so asymptotic space complexity is O(logn)

Compared with "Method 1", "Method 2" has the same time complexity, but because it uses recursion and maintains a structure of four information, it takes a little longer to run and the space complexity is not as good as Method 1. And it’s hard to understand. So what is the significance of this method?

For this question, it is true. But a closer look "Method II", which can not only solve the interval [0, n - 1][0,n−1], can also be used to solve any subinterval [l, r][l,r]problem. If we [0, n - 1][0,n−1], after all the information sub-interval of the partition down are appearing with heap storage memory of the way down, that is, to build a real tree, we can seek to within an arbitrary interval in O (logn) time The answer, we can even modify the value in the sequence, do some simple maintenance, and then we can still find the answer in any interval in O(logn) time. For large-scale queries, the advantage of this method is Reflected. This tree is the magical data structure mentioned above-the line segment tree.

Guess you like

Origin blog.csdn.net/weixin_44471490/article/details/109189317