比较结果
下面值四中算法的的执行时间:
当n的长度为100
ygh.study.algorithm.Demo2.MaxSubSequence1 execute time: 4
ygh.study.algorithm.Demo2.MaxSubSequence2 execute time: 0
ygh.study.algorithm.Demo2.MaxSubSequence4 execute time: 0
ygh.study.algorithm.Demo2.MaxSubSequence3 execute time: 0
当n的长度为1000
ygh.study.algorithm.Demo2.MaxSubSequence1 execute time: 115
ygh.study.algorithm.Demo2.MaxSubSequence2 execute time: 4
ygh.study.algorithm.Demo2.MaxSubSequence4 execute time: 0
ygh.study.algorithm.Demo2.MaxSubSequence3 execute time: 0
当n的长度为10000
ygh.study.algorithm.Demo2.MaxSubSequence1 execute time: 67527
ygh.study.algorithm.Demo2.MaxSubSequence2 execute time: 28
ygh.study.algorithm.Demo2.MaxSubSequence4 execute time: 0
ygh.study.algorithm.Demo2.MaxSubSequence3 execute time: 0
因为第第一中算法 n^3 太消耗时间,为了比较下面三种算法,下面的测试中把N的值增大,把第一个算法的执行注释掉:
当n的长度为100
ygh.study.algorithm.Demo2.MaxSubSequence2 execute time: 0
ygh.study.algorithm.Demo2.MaxSubSequence4 execute time: 0
ygh.study.algorithm.Demo2.MaxSubSequence3 execute time: 0
当n的长度为1000
ygh.study.algorithm.Demo2.MaxSubSequence2 execute time: 3
ygh.study.algorithm.Demo2.MaxSubSequence4 execute time: 0
ygh.study.algorithm.Demo2.MaxSubSequence3 execute time: 0
当n的长度为10000
ygh.study.algorithm.Demo2.MaxSubSequence2 execute time: 24
ygh.study.algorithm.Demo2.MaxSubSequence4 execute time: 1
ygh.study.algorithm.Demo2.MaxSubSequence3 execute time: 0
当n的长度为100000
ygh.study.algorithm.Demo2.MaxSubSequence2 execute time: 2248
ygh.study.algorithm.Demo2.MaxSubSequence4 execute time: 0
ygh.study.algorithm.Demo2.MaxSubSequence3 execute time: 0
当n的长度为1000000
ygh.study.algorithm.Demo2.MaxSubSequence2 execute time: 240431
ygh.study.algorithm.Demo2.MaxSubSequence4 execute time: 1
ygh.study.algorithm.Demo2.MaxSubSequence3 execute time: 1
因为第二种算法n^2也很慢,为了比较分而治之和在线算法的优劣,下面的比较把复制度为n^2的算法注释掉,继续增加N的值
当n的长度为100
ygh.study.algorithm.Demo2.MaxSubSequence4 execute time: 1
ygh.study.algorithm.Demo2.MaxSubSequence3 execute time: 0
当n的长度为1000
ygh.study.algorithm.Demo2.MaxSubSequence4 execute time: 0
ygh.study.algorithm.Demo2.MaxSubSequence3 execute time: 0
当n的长度为10000
ygh.study.algorithm.Demo2.MaxSubSequence4 execute time: 1
ygh.study.algorithm.Demo2.MaxSubSequence3 execute time: 0
当n的长度为100000
ygh.study.algorithm.Demo2.MaxSubSequence4 execute time: 0
ygh.study.algorithm.Demo2.MaxSubSequence3 execute time: 1
当n的长度为1000000
ygh.study.algorithm.Demo2.MaxSubSequence4 execute time: 1
ygh.study.algorithm.Demo2.MaxSubSequence3 execute time: 1
当n的长度为10000000
ygh.study.algorithm.Demo2.MaxSubSequence4 execute time: 9
ygh.study.algorithm.Demo2.MaxSubSequence3 execute time: 10
当n的长度为100000000
ygh.study.algorithm.Demo2.MaxSubSequence4 execute time: 143
ygh.study.algorithm.Demo2.MaxSubSequence3 execute time: 148
感觉在线算法并不是比分而治之算法要要厉害太多,就差几个毫秒
下面是具体的代码实现
1 package ygh.study.algorithm; 2 3 import algorithms.self.tools.IntegerArrayTools; 4 import algorithms.self.tools.MethodExecuteTimeUtils; 5 6 /** 7 * 现在有一个序列{A1,A2,A3,...,An} 求他的子列和的最大值 求f(i,j)=max{0,sum(i,j)Ak} 8 * 9 * @author ygh 2017年3月18日 10 */ 11 public class Demo2 { 12 13 public static void main(String[] args) throws Exception { 14 for(int i=100;i<=100000000;i=i*10){ 15 System.out.println("当n的长度为"+i); 16 int[] arr = IntegerArrayTools.getRandomArray(i, i); 17 Class<?>[] types ={int[].class}; 18 Object[] params={arr}; 19 Demo2 bean = new Demo2(); 20 MethodExecuteTimeUtils.getMethodExecuteTime(bean, params, "MaxSubSequence1", types,true); 21 MethodExecuteTimeUtils.getMethodExecuteTime(bean, params, "MaxSubSequence2", types,true); 22 MethodExecuteTimeUtils.getMethodExecuteTime(bean, params, "MaxSubSequence4", types,true); 23 long start = System.currentTimeMillis(); 24 MaxSubSequence4(arr); 25 long end = System.currentTimeMillis(); 26 long take = end-start; 27 System.out.println("ygh.study.algorithm.Demo2.MaxSubSequence3 execute time: "+take); 28 } 29 30 //测试正确性,因为我的数组都是整数,最大子列和应该是所有项数之和 31 // int maxSubSquence1 = MaxSubSequence1(arr); 32 // System.out.println(maxSubSquence1 == (IntegerArrayTools.getIntegrArraySum(arr))); 33 // int maxSubSquence2 = MaxSubSequence2(arr); 34 // System.out.println(maxSubSquence2 == (IntegerArrayTools.getIntegrArraySum(arr))); 35 // int maxSubSquence3 = MaxSubSequence3(arr,0,arr.length-1); 36 // System.out.println(maxSubSquence3 == (IntegerArrayTools.getIntegrArraySum(arr))); 37 // int maxSubSquence4 = MaxSubSequence4(arr); 38 // System.out.println(maxSubSquence4 == (IntegerArrayTools.getIntegrArraySum(arr))); 39 } 40 41 /** 42 * 第一种算法,使用最暴力的for循环来技术子列和 因为有三重for循环,所以时间复杂度T(n)=O(n^3) 43 * 44 * @param arr 需要计算最大子列和提供数据的数组 45 * @return 如果最大子列和比0大,返回最大子列和,否则,返回0 46 */ 47 public static int MaxSubSequence1(int arr[]) { 48 int length = arr.length; 49 int maxSubSequence = 0; 50 int sum = 0; 51 for (int i = 0; i < length; i++) { 52 for (int j = i; j < length; j++) { 53 sum = 0; 54 for (int k = i; k <= j; k++) { 55 sum = sum + arr[k]; 56 } 57 if (sum > maxSubSequence) { 58 maxSubSequence = sum; 59 } 60 } 61 } 62 return maxSubSequence; 63 } 64 65 /** 66 * 在第一种算法的基础之上,我们来做一次优化,我们发现,k循环,每次都会在计算相同的求和 而且每次求和都比上一次求和多算了一个a[j],那么我们为什么不使用一个临时变量去存储这个 累加的和? 67 * 这样就可以去掉k循环,下面是代码的实现 这样函数时间复杂度T(n)=O(n^2) 68 * 69 * @param arr 需要计算最大子列和提供数据的数组 70 * @return 如果最大子列和比0大,返回最大子列和,否则,返回0 71 */ 72 public static int MaxSubSequence2(int arr[]) { 73 int length = arr.length; 74 int maxSubSequence = 0; 75 76 int sum = 0; 77 for (int i = 0; i < length; i++) { 78 sum = 0; 79 for (int j = i; j < length; j++) { 80 sum = sum + arr[j]; 81 if (sum > maxSubSequence) { 82 maxSubSequence = sum; 83 } 84 } 85 } 86 return maxSubSequence; 87 88 } 89 90 public static int MaxSubSequence3(int arr[], int Left, int Right) { 91 int MaxLeftSum, MaxRightSum; 92 int MaxLeftBorderSum, MaxRightBorderSum; 93 int LeftBorderSum, RightBorderSum; 94 int center, i; 95 96 if (Left == Right) { 97 if (arr[Left] > 0) 98 return arr[Left]; 99 else 100 return 0; 101 } 102 103 center = (Left + Right) / 2; 104 MaxLeftSum = MaxSubSequence3(arr, Left, center); 105 MaxRightSum = MaxSubSequence3(arr, center + 1, Right); 106 107 MaxLeftBorderSum = 0; 108 LeftBorderSum = 0; 109 for (i = center; i >= Left; i--) { 110 LeftBorderSum += arr[i]; 111 if (LeftBorderSum > MaxLeftBorderSum) 112 MaxLeftBorderSum = LeftBorderSum; 113 } 114 115 MaxRightBorderSum = 0; 116 RightBorderSum = 0; 117 for (i = center + 1; i <= Right; i++) { 118 RightBorderSum += arr[i]; 119 if (RightBorderSum > MaxRightBorderSum) 120 MaxRightBorderSum = RightBorderSum; 121 } 122 return Max3(MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum); 123 } 124 125 private static int Max3(int a, int b, int c) { 126 int max; 127 max = a > b ? a : b; 128 max = max > c ? max : c; 129 return max; 130 } 131 132 /** 133 * 在线算法,算法分析,从0到end依次遍历此数组 用maxSubSequence控制总的子列和 用currentSum控制当前的子列和。 134 * 如果currentSum大于maxSubSequence,maxSubSequence = currentSum 如果currentSum小于0,直接舍弃。 135 * 136 * @param arr 137 * @return 138 */ 139 public static int MaxSubSequence4(int arr[]) { 140 int length = arr.length; 141 int currentSum = 0, maxSubSequence = 0; 142 for (int i = 0; i < length; i++) { 143 currentSum = currentSum + arr[i]; 144 if (currentSum > maxSubSequence) { 145 maxSubSequence = currentSum; 146 } else if (currentSum < 0) { 147 currentSum = 0; 148 } 149 150 } 151 return maxSubSequence; 152 } 153 154 }