LeetCode Maximum Subarray
阿新 • • 發佈:2018-12-23
Problem
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [-2,1,-3,4,-1,2,1,-5,4], the contiguous subarray [4,-1,2,1] has the largest sum = 6.
click to show more practice.
More practice: If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
題目的意思是求一個數組,最大子序列的和。 並且,額外要求,在O(n)演算法之外,可以嘗試用分治法解決該問題。
Java 實現
package com.coderli.leetcode.algorithms.easy;
/**
* Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
* <p>
* For example, given the array [-2,1,-3,4,-1,2,1,-5,4],
* the contiguous subarray [4,-1,2,1] has the largest sum = 6.
*
* @author OneCoder 2017-10-31 23:41
*/
public class MaximumSubarray {
public static void main(String[] args) {
MaximumSubarray maximumSubarray = new MaximumSubarray();
System.out.println(maximumSubarray.maxSubArray(new int[]{-2, 1, -3, 4, -1, 2, 1, -5, 4}));
System.out.println(maximumSubarray.maxSubArray(new int[]{-2, -1}));
System.out.println(maximumSubarray.maxSubArray(new int[]{1, -3, 2}));
System.out.println(maximumSubarray.maxSubArray(new int[]{1, -1, -2, 2}));
System.out.println(maximumSubarray.maxSubArrayByDC(new int[]{-2, 1, -3, 4, -1, 2, 1, -5, 4}));
System.out.println(maximumSubarray.maxSubArrayByDC(new int[]{-2, -1}));
System.out.println(maximumSubarray.maxSubArrayByDC(new int[]{1, -3, 2}));
System.out.println(maximumSubarray.maxSubArrayByDC(new int[]{1, -1, -2, 2}));
}
public int maxSubArray(int[] nums) {
if (nums.length == 0) {
return 0;
}
int maxResult = nums[0];
int tempSum = maxResult;
for (int i = 1; i < nums.length; i++) {
if (tempSum <= 0) {
tempSum = nums[i];
} else {
tempSum = tempSum + nums[i];
}
if (tempSum > maxResult) {
maxResult = tempSum;
}
}
return maxResult;
}
public int maxSubArrayByDC(int[] nums) {
if (nums.length == 0) {
return 0;
}
return findMaxSubArray(nums, 0, nums.length - 1);
}
private int findMaxSubArray(int[] nums, int from, int to) {
if (from == to) {
return nums[from];
}
int mid = from + (to - from) / 2;
int maxLeft = findMaxSubArray(nums, from, mid);
int maxRight = findMaxSubArray(nums, mid + 1, to);
int midLeftMax = nums[mid];
int midLeftTempSum = midLeftMax;
for (int i = mid -1; i >= from; i--) {
midLeftTempSum += nums[i];
if (midLeftMax < midLeftTempSum) {
midLeftMax = midLeftTempSum;
}
}
int midRightMax = nums[mid];
int midRightTempSum = midRightMax;
for (int i = mid + 1; i <= to; i++) {
midRightTempSum += nums[i];
if (midRightMax < midRightTempSum) {
midRightMax = midRightTempSum;
}
}
int midMax = midLeftMax + midRightMax - nums[mid];
if (maxLeft >= maxRight && maxLeft >= midMax) {
return maxLeft;
} else if (maxRight > midMax) {
return maxRight;
} else {
return midMax;
}
}
}
分析
解法1是一個線性解法,好處是效率夠快,不足就是丟失最大子序列的位置資訊,最後得到的僅僅是個最大值。
解法2,就是題目要求嘗試的分治解法。即把子序列可能存在位置分三種情況考慮,左、右和橫跨中點。 對於左和右,可以遞迴解決。橫跨的簡單計算即可。