LeetCode | Maximum Subarray
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
.
最优解法:
//O(N)的算法,思想有点类似于双pointer //sum为数组前i项和,如果sum为正,那么就留着,如果为负,那么就舍弃,从第i+1项再尝试取subarray累计和 //如此只需要从前向后一次遍历即可 public class Solution { public static int maxSubArray(int[] A) { int maxSum = Integer.MIN_VALUE; int sum = 0; for(int i=0; i<A.length; i++){ sum += A[i]; if(sum > maxSum) maxSum = sum; if(sum < 0) //当前subarray的前i项和为负,舍弃前i项,重新累计求和 sum = 0; } return maxSum; } }
分治与递归:
//Divide and Conquer: 算法复杂度为O(NlogN) //最大和的subarray有三种可能:即subarray完全位于A的左半部、subarray完全位于A的右半部,或subarray跨越A的中分线 //第三种情况时,subarray必然包含A左的最后一个元素及A右的第一个元素 //将三种情况分别求解,取大者返回 public class Solution { private int maxSumDAC(int[] array, int left, int right){ if(left == right) return array[left]; int center = (left+right)/2; int maxLeftSum = maxSumDAC(array, left, center); //分治与递归 int maxRightSum = maxSumDAC(array, center+1, right); int maxLeftBorderSum = Integer.MIN_VALUE; int leftBorderSum = 0; for(int i=center; i>=left; i--){ leftBorderSum += array[i]; if(leftBorderSum > maxLeftBorderSum) maxLeftBorderSum=leftBorderSum; } int maxRightBorderSum = Integer.MIN_VALUE; int rightBorderSum = 0; for(int i=center+1; i<=right; i++){ rightBorderSum += array[i]; if(rightBorderSum > maxRightBorderSum) maxRightBorderSum=rightBorderSum; } if(maxLeftSum>=maxRightSum) //三者取大返回 return Math.max(maxLeftSum, maxLeftBorderSum+maxRightBorderSum); else return Math.max(maxRightSum, maxLeftBorderSum+maxRightBorderSum); } public int maxSubArray(int[] A) { return maxSumDAC(A, 0, A.length-1); } }
两种遍历方法:
public class Solution { public int maxSubArray(int[] A) { int maxSum = Integer.MIN_VALUE; for(int i=0; i<A.length; i++) //通过三重循环,穷举所有可能子数组的和 for(int j=i; j<A.length; j++){ int sum = 0; for(int k=i; k<=j; k++){ //取i-j内的subarray求和 sum += A[k]; } if(sum > maxSum) maxSum = sum; } //算法为O(N3),提示超时 return maxSum; } } public class Solution { public int maxSubArray(int[] A) { int maxSum = Integer.MIN_VALUE; for(int i=0; i<A.length; i++){ //算法为O(N2),提示超时 int sum = 0; for(int j=i; j<A.length; j++){ //在内循环内,计算i-j的子数组的和 sum += A[j]; if(sum > maxSum) maxSum = sum; } //if(sum > maxSum) maxSum = sum; //注意:判断语句不能放在此处 } //因为在内循环内,每一个j就求了一个子数组和 //如果if放到外面,就相当于整个数组A求和,再与maxSum比了 return maxSum; } }