码迷,mamicode.com
首页 > 编程语言 > 详细

循环一维数组求最大子数组

时间:2015-04-17 09:34:21      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:

题目:

  随机出一个一维数组,设该数组为循环数组,求其最大小子数组。

一、设计思路

  求最大子数组,就求出最大的连续正子数组。

  将数组分为全负和有非负值两种情况。全负求出最大值即可。

  在有非负值的情况下,先判断该随机数组的首尾是否相连,即首尾是否都大于等于零。如果首尾相连,则将该一维数组分为首、中、尾三部分,先求出首尾和S1,再求中间最大连续正子数组和S,令S1和S与maxS相比较,求出最大子数组;如果首尾不相连,则直接借鉴前一种情况中部的算法,求最大正子数组S。

二、源代码

技术分享
  1 //刘双渤,刘洪阳,循环一维数组求最小子数组
  2 package zishuzu;
  3 import java.util.*;
  4 
  5 public class zuidazishuju {
  6 
  7     /**
  8      * @param args
  9      */
 10     public static void main(String[] args) {
 11         // TODO Auto-generated method stub
 12 
 13         Scanner sc = new Scanner(System.in);
 14         
 15         int n,max,min;
 16         int i;
 17         System.out.println("请输入一维数组的长度:");
 18         n = sc.nextInt();
 19         System.out.println("请输入该数组元素的取值范围(请保证前一个值小于后一个值):");
 20         min = sc.nextInt();
 21         max = sc.nextInt();
 22         
 23         int[] a = new int[n];
 24         
 25         for(i = 0;i < n;i++)
 26         {
 27             a[i] = min + (int)(Math.random()*(max-min));
 28         }
 29         
 30         System.out.println("该一维循环随机数组为:");
 31         for(i = 0;i < n;i++)
 32         {
 33             System.out.print(a[i] + "\t");
 34         }
 35         System.out.println();
 36         
 37         int maxS,shouS1 = 0,weiS1 = 0,shouS = 0,weiS = 0,S,S1;
 38         int js,midSta = 0,midSta1 = 0,loci;
 39         int[] loc = new int[n];
 40         int judge = 0;
 41         
 42         for(i = 0;i < n;i++)                       //判断数组元素是否含有非负数
 43         {
 44             if(a[i] >= 0)
 45             {
 46                 judge = 1;
 47                 midSta1 = i;
 48                 break;
 49             }
 50         }
 51         maxS = a[0];
 52         S = 0;
 53         S1 = 0;
 54         js = 0;
 55         loci = 0;
 56         if(judge == 0)                             //所有元素小于零
 57         {
 58             for(i = 0;i < n;i++)
 59             {
 60                 if(a[i] > maxS)
 61                 {
 62                     maxS = a[i];
 63                     loci = 0;
 64                     loc[loci] = i+1;
 65                 }
 66                 else if(a[i] == maxS)
 67                 {
 68                     loci += 1;
 69                     loc[loci] = i +1;
 70                 }
 71             }
 72             System.out.println("最大子数组和为:" + maxS);
 73             System.out.println("数组第一个元素位置为\"1\"");
 74             System.out.print("最大子数组所在位置为:");
 75             for(i = 0;i <= loci;i++)
 76             {
 77                 System.out.print(loc[i] + " ");
 78             }
 79         }
 80         else                                      //正负同时存在
 81         {
 82             if(a[0] >= 0 && a[n - 1] >= 0)            //第一个元素和最后一个元素非负
 83             {
 84                 for(i = 0;i < n;i++)             //从0开始求第一个连续非负子数组
 85                 {
 86                     if(a[i] >= 0)
 87                     {
 88                         S1 += a[i];
 89                         weiS1 = i + 1;
 90                         if(i == n -1)
 91                         {
 92                             shouS1 = 1;
 93                         }
 94                     }
 95                     else
 96                     {
 97                         break;
 98                     }
 99                 }
100                 for(i = n - 1;i > weiS1;i--) //从n-1开始求连续非负子数组
101                 {
102                     if(a[i] >= 0)
103                     {
104                         S1 += a[i];
105                         shouS1 = i +1;
106                     }
107                     else
108                     {
109                         break;
110                     }
111                 }
112                 if(S1 >= maxS)                  //首尾相连子数组与maxS比较
113                 {
114                     maxS = S1;
115                     shouS = shouS1;
116                     weiS = weiS1;
117                 }
118                 for(i = weiS1;i < shouS1 - 1;i++)   //求中间第一个非负数
119                 {
120                     if(a[i] >= 0)
121                     {
122                         midSta = i;
123                         break;
124                     }
125                     else if(i == shouS1 - 2)
126                     {
127                         midSta = i + 1;
128                     }
129                 }
130                 for(i = midSta;i < shouS1 - 1;i++)     //求中间最大连续非负子数组
131                 {
132                     if(a[i] >= 0)
133                     {
134                         S += a[i];
135                         js++;
136                     }
137                     else
138                     {
139                         if(S >= maxS)
140                         {
141                             maxS = S;
142                             weiS = i -1;
143                             shouS = i -js;
144                             js = 0;
145                             S = 0;
146                         }
147                         else
148                         {
149                             S = 0;
150                             js = 0;
151                         }
152                     }
153                 }
154             }
155             else                                     //首尾不是连续非负子数组的情况
156             {
157                 for(i = midSta1;i < n;i++)     //求最大连续非负子数组
158                 {
159                     if(a[i] >= 0)
160                     {
161                         S += a[i];
162                         js++;
163                     }
164                     else
165                     {
166                         if(S >= maxS)
167                         {
168                             maxS = S;
169                             weiS = i ;
170                             shouS = i -js + 1;
171                             js = 0;
172                             S = 0;
173                         }
174                         else
175                         {
176                             S = 0;
177                             js = 0;
178                         }
179                     }
180                 }
181             }
182             System.out.println("最大子数组和为:" + maxS);
183             System.out.println("数组第一个元素位置为\"1\"");
184             System.out.println("最大子数组首位置为:" + shouS);
185             System.out.println("最大子数组尾位置为:" + weiS);
186         }
187         sc.close();
188     }
189 
190 }
View Code

三、设计过程

  先给出随机一维子数组,然后分情况完成。

  全负情况比较简单,但考虑到有相同最大值存在的情况,于是建立一个一维数组loc[n]来保存相同最大值的位置。验证时,发现多最大值的情况下总是为在输出的位置的最前边多一个,修改初始值解决。

  有非负值情况下,在计算首尾和S1时,如果数组全正,则有可能S1为实际值的两倍,因此根据weiS1来判断首尾位置,避免重复相加。在设计中间部分是,如何跳过负值和保存判断最大子数组和是关键,一开始的想法是在出现第一个非负值的情况下保存判断最大子数组和,并将S,js初始化为0,逻辑上不知没有找出错误,最后使用的方法是在每一个负值出现时就判断保存和初始化,成功。

四、实验结果:

有非负值存在且首尾相连:

技术分享

有非负值且首尾不想连:

技术分享

全正:

技术分享

全负:

技术分享

五、结组成员

  刘双渤,刘洪阳。

  共同完成设计思路。

循环一维数组求最大子数组

标签:

原文地址:http://www.cnblogs.com/little-clever/p/4433971.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!