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;
    }
}



原文地址:https://www.cnblogs.com/dosmile/p/6444454.html