LeetCode-53.最大子序和(相关话题:动态规划、分治)

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

进阶:

如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。

1.动态规划

解题思路:利用辅助数组s[],记录到当前位置为止的最大子序和(必须包含当前位置)

关于辅助数组的计算:s[i] = (i-1 >= 0) ? (s[i-1] < 0 ? nums[i] : s[i-1] + nums[i]) : nums[i];

主要在于s[i-1] < 0 ? nums[i] : s[i-1] + nums[i],如果到当前位置的前一位置为止的最大子序和小于0(即s[i-1] < 0),则应该从当前位置重新计算子序和(即s[i] = nums[i]),因为如果累加的话,则一定有s[i] < s[i-1],因此当s[i-1] < 0时,需从当前位置重新计算子序和。

java代码:

class Solution {
    public int maxSubArray(int[] nums) {
        int[] s = new int[nums.length];
        int maxsum = Integer.MIN_VALUE;
        for(int i = 0; i < nums.length; i++){
            s[i] = (i-1 >= 0) ? (s[i-1] < 0 ? nums[i] : s[i-1] + nums[i]) : nums[i];

            maxsum = Math.max(s[i], maxsum);
        }

        return maxsum;
    }
}

2.分治

解题思路:将数组二分为两部分nums1[]、nums2[],则最大子序和一定是下面三种情况中的一种:

  • 最大子序和在nums1[]中
  • 最大子序和在nums2[]中
  • 最大自序和跨越nums1和nums2,此时需计算nums1[]中从右端点开始(包含右端点)的最大子序和和nums2[]中从左端点开始(包含左端点)的最大自序和,求这两个最大自序和之和

java代码:

class Solution {
    public int maxSubArray(int[] nums) {
        return maxSubSum(nums, 0, nums.length-1);
    }

    private int maxSubSum(int[] nums, int start, int end){
        int sum = Integer.MIN_VALUE;
        if(start > end)
            return 0;
        if(start == end)
            return nums[start];

        int middle = (start + end) >> 1;
        int leftMax = maxSubSum(nums, start, middle);
        int rightMax = maxSubSum(nums, middle+1, end);

        int leftSub = nums[middle], rightSub = nums[middle+1];
        int leftTmp = leftSub, rightTmp = rightSub;
        for(int i = middle-1; i >= start; i--){
            leftTmp += nums[i];
            leftSub = Math.max(leftSub, leftTmp);
        }

        for(int i = middle+2; i <= end; i++){
            rightTmp += nums[i];
            rightSub = Math.max(rightSub, rightTmp);
        }
        sum = Math.max(sum, leftMax);
        sum = Math.max(sum, rightMax);
        sum = Math.max(sum, leftSub+rightSub);
        return sum;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_38823568/article/details/81738937