【每周至少一篇 160819】最大子序列和问题的四种求法_Java
2016-08-19 14:02
337 查看
本问题的分析和设计是来自于数据结构与算法分析JAVA语言表述的第二章算法分析中分析,我将其实现,两位小伙伴提提意见。四个示例的时间复杂度由高到低分别是O(n3)、O(n2)、O(nlogn)以及O(N)。可以说不同的复杂度的算法代表着你理解该问题的深度。
原问题是:对于给定的(可能有负数)整数A1、A2、A3…An,求所有子序列中和最大的子序列的值。(同时,为了方便起见,当所有的数均是负数时,则最大子序列的和为0)。
算法一:选定遍历子序列的起点,在起点决定的基础上选定遍历子序列的重点,每次遍历中累加记得子序列的和并进行比较。
算法二:与算法一的区别是:当子序列的起点不变时,子序列的和可以由前一个子序列的值加上添加的元素a[j]。整个算法还是需要遍历该数组的所有子序列,仅仅是将子序列的求和简化在线性时间内。
算法三:采用分治策略(divide and conquer)
算法四:通过理解最大子序列的头部一定不是负数串,一次遍历就可以求出最大子字符串的值,但是这种方法不具有普遍的可分析性,不容易理解且不容易设计。该算法的时间复杂度是O(n)的。
测试时所使用的main函数:
四种方法对应测试的数据均正确。
原问题是:对于给定的(可能有负数)整数A1、A2、A3…An,求所有子序列中和最大的子序列的值。(同时,为了方便起见,当所有的数均是负数时,则最大子序列的和为0)。
算法一:选定遍历子序列的起点,在起点决定的基础上选定遍历子序列的重点,每次遍历中累加记得子序列的和并进行比较。
public static int maxSubSum1(int[] a){ int maxSum = 0; for(int i = 0; i < a.length; i++) for(int j = i; j < a.length; j++){ int thisSum = 0; for(int k = i; k <= j; k++) thisSum += a[k]; maxSum = thisSum > maxSum ? thisSum: maxSum; } return maxSum; }
算法二:与算法一的区别是:当子序列的起点不变时,子序列的和可以由前一个子序列的值加上添加的元素a[j]。整个算法还是需要遍历该数组的所有子序列,仅仅是将子序列的求和简化在线性时间内。
public static int maxSubSum2(int[] a){ int maxSum = 0; for(int i = 0; i < a.length; i++){ int thisSum = 0; for(int j = i; j < a.length; j++){ thisSum += a[j]; maxSum = thisSum > maxSum ? thisSum: maxSum; } } return maxSum; }
算法三:采用分治策略(divide and conquer)
public static int maxSubSum3(int[] a){ return maxSubRec(a, 0, a.length - 1); } private static int maxSubRec(int[] a, int left, int right) { // TODO 自动生成的方法存根 if(left == right) if(a[left] > 0) return a[left]; else return 0; int center = (right - left) / 2 + left; int maxLeftSum = maxSubRec(a, left, center); int maxrightSum = maxSubRec(a, center + 1, right); int maxLeftBorderSum = 0, leftBorderSum = 0; for(int i = center; i >= left; i--){ leftBorderSum += a[i]; maxLeftBorderSum = leftBorderSum > maxLeftBorderSum? leftBorderSum: maxLeftBorderSum; } int maxRightBorderSum = 0, rightBorderSum = 0; for(int i = center + 1; i <= right; i++){ rightBorderSum += a[i]; maxRightBorderSum = rightBorderSum > maxRightBorderSum? rightBorderSum: maxRightBorderSum; } int temp1 = maxLeftSum > maxrightSum? maxLeftSum: maxrightSum; int temp2 = maxLeftBorderSum + maxRightBorderSum; return temp1 > temp2? temp1: temp2; }
算法四:通过理解最大子序列的头部一定不是负数串,一次遍历就可以求出最大子字符串的值,但是这种方法不具有普遍的可分析性,不容易理解且不容易设计。该算法的时间复杂度是O(n)的。
public static int maxSubSum4(int[] a){ int maxSum = 0, thisSum = 0; for(int j = 0 ; j < a.length; j++){ thisSum += a[j]; if(thisSum > maxSum) maxSum = thisSum; else if(thisSum < 0) thisSum = 0; } return maxSum; }
测试时所使用的main函数:
public class MaxSubSum { public static void main(String[] args){ int[] arry = {-2, 11, -4, 13, -5, -2}; System.out.println(maxSubSum1(arry)); System.out.println(maxSubSum2(arry)); System.out.println(maxSubSum3(arry)); System.out.println(maxSubSum4(arry)); } }
四种方法对应测试的数据均正确。
相关文章推荐
- 【每周至少一篇 160727】简单的选择问题(select problem)_Java
- 连续子序列最大和问题的四种经典解答
- java求最大子序列的和的问题
- HDU1003 Max Sum 最大子序列和的问题【四种算法分析+实现】
- java 动态规划最大公共子序列问题
- 算法入门:最大子序列和的四种算法(Java)
- [leetcode]分治法求解最大子序列问题——Java实现
- 【每周至少一篇 160811】函数对象_Java
- 最大连续子序列问题的java实现
- java实现最大子序列问题——————性能最优的算法
- 总结java最大连续子序列和的问题
- 【每周至少一篇 160811(上周补传)】泛型_Java
- 连续子序列最大和问题精讲(java实现)
- 最大子序列和问题四种解(O)
- [C++]四种方式求解最大子序列求和问题
- [C++]四种方式求解最大子序列求和问题
- java 之连续子序列最大和问题的四个解法
- java最大子序列和问题的求解
- 四种求最大子序列和问题的解
- 最大子序列问题