您的位置:首页 > 其它

【算法导论学习-007】最大子数组和问题(Maximum subarray problem)

2014-08-07 21:41 615 查看
问题来源:【算法导论】P68 4.1节,求得一个数组中连续的子数组中最大的和。

方案1——【算法导论】70页:暴力方法

<pre name="code" class="java"><span style="font-size:18px;">/*暴力方法*/
public static int[] forceMethod(int[] array) {
int sum=Integer.MIN_VALUE;
int tempSum=0;
int start=-1;
int end=-1;
int i=0;
for (i = 0; i < array.length; i++) {
/*不要写成j=i+1*/
for (int j = i; j < array.length; j++) {
tempSum=0;
for (int k = i; k <=j; k++) {
tempSum+=array[k];
}
if (tempSum>sum) {
sum=tempSum;
end=j;
start=i;
}
}
}
int[] result={start,end,sum};
return result;
}</span>



方案2——【算法导论】72页:分治法(复杂度O(nlgn))

public class FindMaxSubArray {

/**
* @param args
*/
public static void main(String[] args) {
// TODO 自动生成的方法存根
int[] array={4,-3,2};
int[] result=FindMaxMumSubarray(array, 0,array.length-1);
System.out.println("起点位置:"+result[0]+";终止位置:"+result[1]+";最大子数组和:"+result[2]);

}

public static int[] FindMaxMumSubarray(int[] array,int low,int high) {
int[] leftResult;
int[] rightResult;
int[] crossResult;
/*终止条件*/
if (low==high) {
int[] result={low,high,array[low]};
return result;
}
else {
int mid=(high-low)>>>1;
/*寻找左数组中的最大子数组*/
leftResult=FindMaxMumSubarray(array, low, mid);
/*寻找右数组中的最大子数组*/
rightResult=FindMaxMumSubarray(array, mid+1, high);
/*寻找跨越中间位置的最大子数组*/
crossResult=FindMaxCrossingSubArray(array, low, mid, high);
/*比较三者谁最大,最大的返回*/
if (leftResult[2]>=rightResult[2]&&leftResult[2]>=crossResult[2]) {
return leftResult;
}else if (rightResult[2]>=leftResult[2]&&rightResult[2]>=crossResult[2]) {
return rightResult;
}else {
return crossResult;
}
}
}
/*寻找跨越中间点的最大子数组,返回值为左位置、有位置、数组和*/
public static int[] FindMaxCrossingSubArray(int[] array,int low,int mid,int high) {
int leftSum=Integer.MIN_VALUE;
int sum=0;
int maxLeft=Integer.MIN_VALUE;
for (int i = mid; i >=low; i--) {
sum+=array[i];
if (sum>leftSum) {
leftSum=sum;
maxLeft=i;
}
}
int rightSum=Integer.MIN_VALUE;
sum=0;
int maxRight=Integer.MIN_VALUE;
for (int i = mid+1; i <=high; i++) {
sum+=array[i];
if (sum>rightSum) {
rightSum=sum;
maxRight=i;
}
}
int[] result={maxLeft,maxRight,leftSum+rightSum};
return result;
}
}
方案3——Kadane's algorithm(复杂度O(n))

参考:http://en.wikipedia.org/wiki/Maximum_subarray_problem

思路,设置辅助的和auxiliarySum,如果auxiliarySum小于0表明需要重置为下一个,否则累加,只要sum<auxiliarySum就表明需要更新sum

public class Test {
public static void main(String[] args) {
int[] a = { 1, -2, 3, 10, -4, 7, 2, -5 };
System.out.println("最大子数组的下标为" + getMaxSumofArray(a)[0] + ":"
+ getMaxSumofArray(a)[1] + ",和为:" + getMaxSumofArray(a)[2]);
}

public static int[] getMaxSumofArray(int[] args) {
int sum = 0;
int auxiliarySum = 0;
int from = 0;
int end = 0;
for (int i = 0; i < args.length; i++) {
/*关键点1:和为小于0表明需要重置开始位置,重新计算*/
if (auxiliarySum < 0) {
auxiliarySum = args[i];
from = i;
} else {
auxiliarySum += args[i];
}
/*关键点2:如果暂时加了负数,auxiliarySum<sum,如果再加正数导致auxiliarySum>sum则更新sum*/
if (sum < auxiliarySum) {
sum = auxiliarySum;
end = i;
}
}
int[] result = { from, end, sum };
return result;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: