首页 > 代码库 > 最大子段和
最大子段和
1 package digui_fenzhi; 2 3 //最大字段和 4 import java.util.Random; 5 import java.util.Scanner; 6 7 class SimpleAlgorithm//简单算法 8 { 9 int maxSum(int[] a) 10 { 11 int sum=0; 12 for(int i=0;i<a.length;i++) 13 for(int j=i;j<a.length+1;j++) 14 { 15 int thissum=0; 16 for(int k=i;k<j;k++) 17 thissum+=a[k]; 18 if(thissum>sum) 19 { 20 sum=thissum; 21 } 22 } 23 return sum; 24 } 25 } 26 27 class DivideConquer//分治法 28 { 29 private int maxSubSum(int[] a,int left,int right) 30 { 31 int sum=0; 32 int s1=0,s2=0,lefts=0,rights=0; 33 int center,leftsum,rightsum; 34 if(left==right) 35 { 36 if(a[left]>0) 37 sum=a[left]; 38 else 39 sum=0; 40 } 41 else 42 { 43 center=(left+right)/2; //划分 44 leftsum=maxSubSum(a,left,center); //对应情况1,递归求解 45 rightsum=maxSubSum(a,center+1,right); //对应情况2,递归求解 46 //求解s1 47 for(int i=center;i>=left;i--) 48 { 49 lefts=lefts+a[i]; 50 if(lefts>s1) 51 s1=lefts; 52 } 53 //再求解s2 54 for(int j=center+1;j<=right;j++) 55 { 56 rights=rights+a[j]; 57 if(rights>s2) 58 s2=rights; 59 } 60 sum=s1+s2; //计算情况3的最大子段和 61 if(sum<leftsum) 62 sum=leftsum; 63 if(sum<rightsum) 64 sum=rightsum; 65 } 66 return sum; 67 } 68 int maxSum(int[] a) 69 { 70 return maxSubSum(a,0,a.length-1); 71 72 } 73 } 74 75 class DynamicProgramming//动态规划法 76 { 77 int maxSum(int[] a) 78 { 79 int sum=0; 80 int b=0; 81 for(int i=0;i<a.length;i++) 82 { 83 if(b>0) b+=a[i]; 84 else b=a[i]; 85 if(b>sum)sum=b; 86 } 87 return sum; 88 } 89 90 } 91 92 class Optimal{//判断最优算法 93 public void Judge(long time1,long time2,long time3){ 94 long b=time1; 95 if(time1 > time2){ 96 b = time2; 97 } 98 if(b > time3){ 99 b = time3;100 }101 if(b==time1){102 System.out.println("最优算法是简单算法!");103 }104 else if(b== time2){105 System.out.println("最优算法是分治算法!");106 }107 else if(b== time3){108 System.out.println("最优算法是动态规划算法!");109 }110 111 }112 }113 public class SubSegment {114 public static void main(String[] args) {115 System.out.println("请输入整数个数n:");116 Scanner in = new Scanner(System.in);117 int n = in.nextInt();118 int a1[]=new int[n+1];119 int a2[]=new int[n+1];120 int a[]=new int[n+1];121 Random random = new Random();122 System.out.println("得到的随机数是:");123 for(int i=0;i<=n;i++) 124 { 125 a1[i] =(int)Math.floor((random.nextDouble()*10.0)); //产生0-10之间随机数 126 a2[i] =(int)Math.floor((random.nextDouble()*10.0)); //产生0-10之间随机数 127 a[i]=a1[i]-a2[i];128 System.out.print(a[i]+" ");129 }130 SimpleAlgorithm s = new SimpleAlgorithm();131 DivideConquer d = new DivideConquer();132 DynamicProgramming p = new DynamicProgramming();133 134 long start1= System.currentTimeMillis();135 System.out.println(" ");136 System.out.println("简单算法算得最大字段和为:\n"+s.maxSum(a));137 long end =System.currentTimeMillis();138 long time = (end - start1);139 System.out.println("用时:" + time + "毫秒!");140 141 long start2 = System.currentTimeMillis();142 System.out.println("分治算法算得最大字段和为:\n"+d.maxSum(a));143 long end1 =System.currentTimeMillis();144 long time1 = (end1 - start2);145 System.out.println("用时:" + time1 + "毫秒!");146 147 long start3 = System.currentTimeMillis();148 System.out.println("动态规划算法算得最大字段和为:\n"+p.maxSum(a));149 long end2=System.currentTimeMillis();150 long time2 = (end2- start3);151 System.out.println("用时:" + time2 + "毫秒!");152 153 Optimal o = new Optimal();154 o.Judge(time, time1, time2);155 156 }157 158 }
运算结果:
动态规划算法:
该代码从头到尾扫描一次,如果只有一项,则最大子段和是它本身,不管是否为负数还是正数。假设第二项为正数的话,显然最大子段和就是第二项本身了,该怎样解决了呢,这样想,因为这是求连续子段和,倘若该项的前n-1项连续子段和为负数,则最大子段和max就会改变,因为一个数加上一个负数,值会减小。所以当前n-1项连续子段和为负数时,就舍弃这一段,从下一项开始。但注意,最大连续子段和中的元素可以允许有负数的存在,此时就需要设置一个max来保存最大值的情况,如果增加,则更新max的情况,否则不更新。
/* 动态规划法思想:将较大的问题分解成较小的问题,先求解子问题, 然后通过子问题的解得到原问题的解,经过分解的子问题之间并不是 相互独立的。*/
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。