问题描述:给定数组A,求解A的和最大的非空连续子数组,数组为空时返回0。
算法思想:记数组A为A[low,high],取中间值mid=low+(high-low)/2,将A分为[low,mid]和[mid+1,high]两个子数组A的最大子数组分布为有以下三种情况:
1.全部位于[low,mid];
2.全部位于[mid+1,high];
3.跨越两子数组,记为[i,j] 其中i<=mid<j;
对三种情况分别讨论
1、2递归调用,将两个子数组当做完整数组求解其最大子数组;
3.以A[mid]为起点,向左向右依次遍历,求的左边最大连续子数组和右边最大连续子数组,拼接起来即是该种情况下原数组最大子数组
取三种情况下的最大值,即为A的最大子数组。
算法java实现
public class maxSubArray {
public static void main(String[] args) {
int[] A=new int[] {3,9,-2,0,4,6,-2,-1,3,7};//给定一个数组
//int[] A=new int[] {3,-1,9,-1};//给定一个数组
System.out.println(maxSubArray(A,0,A.length-1));
}
/**
*
* @param num
* @param low 左下标
* @param high 右下标
* @return maxSubArraySum
*/
public static int maxSubArray(int[] num,int low,int high) {
if(low==high) return 0;
int mid=low+(high-low)/2;
int maxLeftSum=maxSubArray(num,low,mid);//情况1
int maxRightSum=maxSubArray(num,mid+1,high);//情况2
int maxCrossLeftSum=num[mid];
//从num[mid]向左遍历
for(int i=mid-1;i>=low;i--) {
if(maxCrossLeftSum+num[i]>maxCrossLeftSum)
maxCrossLeftSum+=num[i];
else
break;
}
int maxCrossRightSum=num[mid+1];
for(int i=mid+2;i<=high;i++) {
if(maxCrossRightSum+num[i]>maxCrossRightSum)
maxCrossRightSum+=num[i];
else
break;
}
int maxCrossSum=maxCrossLeftSum+maxCrossRightSum;//情况3
return Math.max(Math.max(maxLeftSum,maxRightSum),maxCrossSum);
}
}