LeetCode(1), Maximum Subarray, 最大子序数组

Maximum Subarray

Description

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

Example:

Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.

Follow up:

If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

Solution

1. Kadane’s algorithms takes O(n) time.

对于第i个数组元素,对应子数组以第i个元素结尾为[M, nums[i]][nums[i]],其中M为以第i-1数组元素结束的最大子数组。
如果sum(M)+nums[i] > nums[i],那么以第i个数组元素结尾的子数组为[M, nums[i]],如果sum(M)+nums[i] <= nums[i],那么以第i个数组元素结尾的子数组为[nums[i]]
遍历每一个数组元素,计算以该数组元素结尾的最大子数组的和,并且在遍历过程中,保留其最大值max_global
Time complexity: O(n)

class Solution {
    public int maxSubArray(int[] nums) {
        int max_global = nums[0];
        int max_curr = nums[0];
        for (int i = 1; i < nums.length; i++) {
            max_curr = Math.max(max_curr+nums[i], nums[i]);
            max_global = Math.max(max_curr, max_global);
        }
        return max_global;
    }
}

2. Divide and Conquer

  1. 将数组分为两个子数组, divide
  2. 返回下列三项中的最大值:
    • 左半部分数组的 Maximum subarray sum(递归调用), conquer
    • 右半部分数组的 Maximum subarray sum (递归调用), conquer
    • 子数组包括中间的分割点的 Maximum subarray sum (linear time), combine

Time Complexity: T[n] = 2T[n/2] + O(n) --> O(nlg(n))

class Solution {
    public int maxSubArray(int[] nums) {
        return maxSubArray(nums, 0, nums.length-1);
    }
    
    private int maxSubArray(int[] nums, int lo, int hi) {
        // Base case: when only one element, return it
        if (lo == hi)
            return nums[lo];
        
        // Find the middle point
        int mid = (lo + hi) / 2;
        
        /* Return maximum of following three possible cases: 
        a) Maximum subarray sum in left half 
        b) Maximum subarray sum in right half 
        c) Maximum subarray sum such that the subarray crosses the midpoint */
        return Math.max(Math.max(maxSubArray(nums, lo, mid), maxSubArray(nums, mid+1, hi)), maxCrossingSum(nums, lo, mid, hi));
    }
    
    private int maxCrossingSum(int[] nums, int lo, int mid, int hi) {
        // go from mid to lo, find the largest subarray sum
        int leftMaxSum = Integer.MIN_VALUE, leftSum = 0;
        for (int i = mid; i >= lo; i--) {
            leftSum += nums[i];
            leftMaxSum = Math.max(leftSum, leftMaxSum);
        }
        
        // go from mid to hi, find the largest subarray sum
        int rightMaxSum = Integer.MIN_VALUE, rightSum = 0;
        for (int i = mid+1; i <= hi; i++) {
            rightSum += nums[i];
            rightMaxSum = Math.max(rightSum, rightMaxSum);
        }
        
        return leftMaxSum + rightMaxSum;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值