三种算法求最大子段和问题——Java实现

来源:互联网 发布:宽带网络布线 编辑:程序博客网 时间:2024/06/06 20:03
  1. 给定由n个整数组成的序列(a1, a2, …, an),求该序列的子段和的最大值,当所有整数均为负整数时,其最大子段和为0。  
  2.   
  3. LargestSubsegmentSum1.java                        //蛮力算法  
  4.   
  5. import java.util.*;  
  6.   
  7. public class LargestSubsegmentSum1  
  8. {  
  9.  public static void main(String[] args)  
  10.  {  
  11.   /** 
  12.    *从键盘输入所要求的序列的长度n 
  13.    */  
  14.   Scanner in=new Scanner(System.in);  
  15.     
  16.   System.out.println("Please enter the length of segment you want to make(输入你要求的序列的长度):");  
  17.   int n=in.nextInt();  
  18.   /** 
  19.    *从键盘输入所要求的序列,存储在a[n]中 
  20.    */  
  21.   int[] a=new int[n];  
  22.   System.out.println("Now,please enter the elements of the segment you want(现在请依次输入这个序列包含的元素(整数)):");  
  23.   for(int i=0;i<n;i++)  
  24.   {  
  25.    a[i]=in.nextInt();  
  26.   }  
  27.     
  28.         double startTime=System.currentTimeMillis();//starttime  
  29.         /** 
  30.    *求解最大子段和存在maxSum中 
  31.    */  
  32.   int maxSum=a[0];  
  33.   for(int i=0;i<n-1;i++)  
  34.   {  
  35.    int temp=a[i];  
  36.    for(int j=i+1;j<n;j++)  
  37.    {  
  38.     temp+=a[j];  
  39.     if(temp>maxSum)  
  40.      maxSum=temp;  
  41.    }  
  42.   }  
  43.   double endTime=System.currentTimeMillis();//endtime  
  44.   /** 
  45.    *打印输出求解结果和程序所用时间 
  46.    */  
  47.   System.out.println("The largest sub-segment sum is(最大子段和是):"+maxSum);  
  48.   System.out.println("Basic Statements take(基本语句用时) "+(endTime-startTime)+" milliseconds!");  
  49.  }  
  50. }  
  51.   
  52. ***************************************************************************  
  53.   
  54. 分治算法描述:  
  55.   
  56.     int MaxSum(int a[ ], int left, int right)  
  57.   
  58.    {  
  59.   
  60.        sum=0;  
  61.   
  62.        if (left= =right) {      //如果序列长度为1,直接求解  
  63.   
  64.            if (a[left]>0) sum=a[left];  
  65.   
  66.            else sum=0;  
  67.   
  68.        }  
  69.   
  70.       else {  
  71.   
  72.           center=(left+right)/2;    //划分  
  73.   
  74.           leftsum=MaxSum(a, left, center);    
  75.   
  76.                                                        //对应情况①,递归求解  
  77.   
  78.           rightsum=MaxSum(a, center+1, right);    
  79.   
  80.                                                        //对应情况②,递归求解  
  81.   
  82.  s1=0; lefts=0;              //以下对应情况③,先求解s1  
  83.   
  84.         for (i=center; i>=left; i--)  
  85.   
  86.         {  
  87.   
  88.             lefts+=a[i];  
  89.   
  90.             if (lefts>s1) s1=lefts;   }  
  91.   
  92.         s2=0; rights=0;             //再求解s2  
  93.   
  94.         for (j=center+1; j<=right; j++)  
  95.   
  96.         {   
  97.   
  98.             rights+=a[j];  
  99.   
  100.             if (rights>s2) s2=rights;    }  
  101.   
  102.         sum=s1+s2;              //计算情况③的最大子段和   
  103.   
  104.         if (sum<leftsum) sum=leftsum;    
  105.   
  106.                      //合并,在sum、leftsum和rightsum中取较大者  
  107.   
  108.         if (sum<rightsum) sum=rightsum;     }  
  109.   
  110.      return sum;  }   
  111.   
  112. LargestSubsegmentSum2.java                                //分治算法  
  113.   
  114.    
  115.   
  116. import java.util.*;  
  117.   
  118. public class LargestSubsegmentSum2  
  119. {  
  120.  public static void main(String[] args)  
  121.  {  
  122.   /** 
  123.    *从键盘输入所要求的序列的长度n 
  124.    */  
  125.   Scanner in=new Scanner(System.in);  
  126.   System.out.println("Please enter the length of segment you want to make(输入你要求的序列的长度):");  
  127.   int n=in.nextInt();  
  128.   /** 
  129.    *从键盘输入所要求的序列,存储在a[n]中 
  130.    */  
  131.   int[] a=new int[n];  
  132.   System.out.println("Now,please enter the elements of the segment you want(现在请依次输入这个序列包含的元素(整数)):");  
  133.   for(int i=0;i<n;i++)  
  134.   {  
  135.    a[i]=in.nextInt();  
  136.   }  
  137.   /** 
  138.    *调用函数MaxSum()求解出结果 
  139.    */  
  140.   double startTime=System.currentTimeMillis();//starttime  
  141.   int maxSum=MaxSum(a,0,n);  
  142.   double endTime=System.currentTimeMillis();//endtime  
  143.   /** 
  144.    *打印输出结果和程序运行所用时间 
  145.    */  
  146.   System.out.println("The largest sub-segment sum is(最大子段和是):"+maxSum);  
  147.   System.out.println("Basic Statements take(基本语句用时) "+(endTime-startTime)+" milliseconds!");  
  148.  }  
  149.  /** 
  150.    *设计求解最大子段和的函数MaxSum() 
  151.    */  
  152.  public static int MaxSum(int[] a,int left,int right)  
  153.  {  
  154.   int maxSum=0;  
  155.   if(left==right)  
  156.   {  
  157.    if(a[0]>0)  
  158.     maxSum=a[0];  
  159.   }  
  160.   else  
  161.   {  
  162.    int center=(left+right)/2;  
  163.    int maxSum1=MaxSum(a,left,center);  
  164.    int maxSum2=MaxSum(a,center+1,right);  
  165.    int s1=0;  
  166.    int lefts=0;  
  167.    for(int i=center;i>=left;i--)  
  168.    {  
  169.     lefts+=a[i];  
  170.     if(lefts>s1)  
  171.      s1=lefts;  
  172.    }  
  173.      
  174.    int s2=0;  
  175.    int rights=0;  
  176.    for(int j=center+1;j<right;j++)  
  177.    {  
  178.     rights+=a[j];  
  179.     if(rights>s2)  
  180.      s2=rights;  
  181.    }  
  182.      
  183.    maxSum=s1+s2;  
  184.    if(maxSum<maxSum1)  
  185.     maxSum=maxSum1;  
  186.    if(maxSum<maxSum2)  
  187.     maxSum=maxSum2;  
  188.   }  
  189.   return maxSum;  
  190.  }  
  191. }  
  192.   
  193. ***********************************************************************************************  
  194.   
  195. LargestSubsegmentSum3.java                                          //动态规划算法  
  196.   
  197.    
  198.   
  199. import java.util.*;  
  200.   
  201. public class LargestSubsegmentSum3  
  202. {  
  203.  public static void main(String[] args)  
  204.  {  
  205.   /** 
  206.    *从键盘输入所要求的序列的长度n 
  207.    */  
  208.   Scanner in=new Scanner(System.in);  
  209.     
  210.   System.out.println("Please enter the length of segment you want to make(输入你要求的序列的长度):");  
  211.   int n=in.nextInt();  
  212.   /** 
  213.    *从键盘输入所要求的序列,存储在a[n]中 
  214.    */  
  215.   int[] a=new int[n];  
  216.   System.out.println("Now,please enter the elements of the segment you want(现在请依次输入这个序列包含的元素(整数)):");  
  217.   int i;  
  218.   for(i=0;i<n;i++)  
  219.   {  
  220.    a[i]=in.nextInt();  
  221.   }  
  222.   /** 
  223.    *求解最大子段和存在maxSum中 
  224.    */  
  225.   double startTime=System.currentTimeMillis();//starttime  
  226.   int maxSum=0;  
  227.   int[] b=new int[n];  
  228.   b[0]=0;  
  229.   for(int j=1;j<n;j++)  
  230.   {  
  231.    if(b[j-1]>0)  
  232.     b[j]=b[j-1]+a[j];  
  233.    else  
  234.    {  
  235.     b[j]=a[j];  
  236.     i=j;  
  237.    }  
  238.   }  
  239.   for(int j=0;j<n;j++)  
  240.   {  
  241.    if(b[j]>maxSum)  
  242.     maxSum=b[j];  
  243.   }  
  244.   double endTime=System.currentTimeMillis();//endtime  
  245.   /** 
  246.    *打印输出结果和程序运行所用时间 
  247.    */  
  248.   System.out.println("The largest sub-segment sum is(最大子段和是):"+maxSum);  
  249.   System.out.println("Basic Statements take(基本语句用时) "+(endTime-startTime)+" milliseconds!");  
  250.  }  
  251. }  
  252.  
0 0