【算法导论学习-007】最大子数组和问题(Maximum subarray problem)
2014-08-07 21:41
615 查看
问题来源:【算法导论】P68 4.1节,求得一个数组中连续的子数组中最大的和。
方案1——【算法导论】70页:暴力方法
方案2——【算法导论】72页:分治法(复杂度O(nlgn))
参考:http://en.wikipedia.org/wiki/Maximum_subarray_problem
思路,设置辅助的和auxiliarySum,如果auxiliarySum小于0表明需要重置为下一个,否则累加,只要sum<auxiliarySum就表明需要更新sum
方案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; } }
相关文章推荐
- 【算法导论学习笔记】最大子数组问题
- 动态规划法(八)最大子数组问题(maximum subarray problem)
- 最大子数组问题(动态规划)--【算法导论】
- 算法学习--3 最大子数组和以及进阶问题
- 【算法基础】算法导论-最大子数组问题
- 最大子数组求解问题(算法导论)
- 算法导论:分治策略__最大子数组问题
- 最大子数组问题(分治法)--【算法导论】
- 算法导论 4.1-5 最大子数组问题 线性时间算法 C++简单实现
- 【算法导论】最大子数组问题
- Maximum subarray -- 最大子数组问题(C++)
- 算法学习笔记----最大子数组问题
- [算法导论]练习4.1-5最大连续子数组问题
- 最大子数组问题(动态规划)--【算法导论】
- 4.1最大数组问题(算法导论)
- 算法导论--分治策略求解最大子数组问题
- 算法导论之最大子数组问题 C语言实现
- 算法导论_最大子数组问题(分治策略)
- 小sugar呀____最大子数组问题(算法导论)
- 【算法学习】最大子数组问题的分治法求解