最大子数组问题
2015-03-17 11:24
239 查看
package com.algorithm.sort; /** * Created by louis on 2015/3/16. */ // 最大子数组问题 该类中采用三种方法求解 public class MaxSubArray { /* 暴力求解:先找出从第1个元素开始的最大子数组,而后再从第2个元素开始找出从第2个 元素开始的最大子数组,依次类推,比较得出最大的子数组。 T(n)=O(n^2) */ public static int bruteForce(int[] data){ int max=0; for (int i = 0; i < data.length-1; i++) { int curSum=0; for (int j = i; j < data.length - 1; j++) { curSum += data[j]; if (curSum > max) { max=curSum; } } } return max; } /* 分治求解:假定数组 A[low..high],将数组A从中间分为两个字数组A[low..mid]和A[mid+1,high], 那么任意连续的字数组A[i..j]一定位于一下三个位置 (1) 完全位于子数组 A[low..mid],即 low<=i<=j<=high (2) 完全位于子数组 A[mid+1..high],即 mid<i<=j<=high (3) 位于跨域中点,即 low<=i<=mid<=j<=high 时间复杂度: T(n)=2T(n/2)+O(n), 递推得到 T(n)=O(nlgn) Pseudo code: find-maximum-subArray(A,low,high){ if high==low return (low,high,A[low]) else mid=(low+high)/2 (left-low,left-hig,left-sum)= find-maximum-subArray(A,low,mid) (right-low,right-high,right-sum)= find-maximum-subArray(A,mid+1,high) (cross-low,cross-high,cross-sum)= find-max-crossing-subArray(A,low,mid,high) if left-sum>=right-sum && left-sum>=cross-sum return (left-low,left-high,left-sum) else if right-sum>=left-sum && right-sum>=cross-sum return (right-low,right-high,right-sum) else return (cross-low,cross-high,cross-sum) } */ public static int findMaximumSubArray(int[] data,int low,int high){ if(low==high){ return data[low]; // base case: only one element }else{ int mid=(low+high)/2; int leftSum = findMaximumSubArray(data, low, mid); int rightSum = findMaximumSubArray(data, mid + 1, high); int crossSum = findMaxCrossSubArray(data, low, mid, high); if (leftSum >= rightSum && leftSum >= crossSum) { return leftSum; }else if(rightSum>=leftSum&&rightSum>=crossSum){ return rightSum; }else{ return crossSum; } } } /* Pseudo code: find-max-cross-subArray(A,low,mid,high){ left-sum=-Infinite sum=0 for i=mid downTo low sum+=A[i] if sum>left-sum left-sum=sum max-left=i right-sum=-Infinite sum=0 for j=mid+1 to high sum+=sum[j] if sum>right-sum right-sum=sum max-right=j return (max-left,max-right,left-sum+right-sum) } */ private static int findMaxCrossSubArray(int[] data, int low, int mid, int high) { int leftSum = Integer.MIN_VALUE; int sum=0; int maxLeft; //left max index int maxRight; for (int i = mid; i >= low; i--) { sum += data[i]; if (sum > leftSum) { leftSum=sum; maxLeft=i; // marker the index; no use } } int rightSum = Integer.MIN_VALUE; sum=0; for (int j = mid + 1; j <= high; j++) { sum += data[j]; if (sum > rightSum) { rightSum=sum; maxRight=j; } } return leftSum + rightSum; } /* 线性时间算法:该算法在每次元素累加和小于0时,从下一个元素重新开始累加; 因为元素有正有负,因此子序列的最大和一定大于0; 该算法只对数据进行一次扫描,一旦元素被读入并被处理,它就不再需要被记忆 因此,如果数组在磁盘或磁带上,他就可以被顺序读入,在主存中不必存储数组的任何部分。 不仅如此,在任意时刻,该算法都能对它已经读入的数据给出最大子数组(另外两种算法不具有这种特性)。 具有这种特性的算法叫做联机算法。 时间复杂度:T(n)=O(n) 最优算法 */ public static int linearTime(int[] data){ int maxSum=Integer.MIN_VALUE; int curSum=0; for (int i = 0; i < data.length; i++) { curSum += data[i]; if (curSum > maxSum) { maxSum=curSum; } if (curSum < 0) { curSum = 0; } } return maxSum; } public static void main(String[] args) { int[] data = new int[]{13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7}; int max=0; // max = MaxSubArray.bruteForce(data); // max = MaxSubArray.findMaximumSubArray(data, 0, data.length - 1); max = MaxSubArray.linearTime(data); System.out.println(max); } }
相关文章推荐
- 求数组子数组之和最大值问题-犯了一个很2B的错误,函数参数啊函数参数
- 微软面试题---求子数组最大乘积问题
- 用递归法求解一个数组中的最大值和最小值的问题
- 树状数组求区间最大值一类问题
- 数组问题之一维最大字段和问题<Java实现>
- 经典的求数组中最大值及其位置的问题.
- 最大子数组问题 时间复杂度为Θ(n)
- 数组最大子序列和问题
- 数组分段和最大值最小问题
- 子数组最大和问题
- 求数组连续最大和问题
- 怪异问题 调试到位置(test dword ptr [eax],eax ; probe page.)局部数组变量定义所分配的最大空间为1M
- HDU 1024 Max Sum Plus Plus(动态规划,给定一个数组,求其分成m个不相交子段和最大值的问题)
- 编程之美2.14扩展问题1 求子数组和的最大值(首尾可以相连)
- 编程之美2.14 子数组之和的最大值 扩展问题(首尾相连)
- 【开放 5月18日 发布】:子数组的最大乘积问题_____问题简单,请思考如何逐步降低时间复杂度,跟帖回复,群内讨论.
- 编程之美2.14扩展问题2 求数组的子数组之和的最大值并给出子数组的起始终止位置
- 数组最大差值问题
- 求子数组的最大和问题
- 算法导论_最大子数组问题(分治策略)