求一个序列的连续子列和的最大值

本文对比了四种不同算法在求解子序列和问题上的执行效率,通过逐步增加输入规模,观察并分析了各种算法的时间复杂度表现,揭示了在线算法与分治算法在大规模数据集上的实际差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

比较结果

下面值四中算法的的执行时间:

当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 }
View Code

 

转载于:https://www.cnblogs.com/yghjava/p/6576181.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值