最大子段和

  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 }

运算结果:最大子段和_第1张图片

动态规划算法:

该代码从头到尾扫描一次,如果只有一项,则最大子段和是它本身,不管是否为负数还是正数。假设第二项为正数的话,显然最大子段和就是第二项本身了,该怎样解决了呢,这样想,因为这是求连续子段和,倘若该项的前n-1项连续子段和为负数,则最大子段和max就会改变,因为一个数加上一个负数,值会减小。所以当前n-1项连续子段和为负数时,就舍弃这一段,从下一项开始。但注意,最大连续子段和中的元素可以允许有负数的存在,此时就需要设置一个max来保存最大值的情况,如果增加,则更新max的情况,否则不更新。

/* 动态规划法思想:将较大的问题分解成较小的问题,先求解子问题, 然后通过子问题的解得到原问题的解,经过分解的子问题之间并不是 相互独立的。*/

你可能感兴趣的:(最大子段和)