一、设计思路
之前我们已经写出了环形一维数组的最大子数组,现在我们只需要先随机出二维数组,将二维数组转化为一维数组,再调用这个求一维最大子数组的函数,即可求出结果。
将二维数组转化为一维数组,再通过一维数组间接求出二维数组的最大子数组的方法与欢龙的方法异曲同工。我的方法是以一行为起点,然后从这一行一直加到最后一行,每加一行即产生可以向一维数组函数传递的一维数组。起始行依次向下递增,一直到最后一行。
二、代码
1 //环形一维数组求最大子数组 2 package erwei; 3 4 public class oneArray { 5 6 private int i; 7 public static int maxS; 8 public int maxShou; 9 public int maxWei; 10 void getMax(int[] a,int n){ 11 boolean x = false; 12 for(i = 0;i < n;i++) 13 { 14 if(a[i] >= 0) 15 { 16 x = true; 17 break; 18 } 19 } 20 21 int sum=0,s1=0,s2=0,loc=0,loc1=0; 22 if(x == true) //有正数的情况下 23 { 24 for(i = 0;i < n;i++) //全部为正数的情况下 25 { 26 s2 += a[i]; 27 if(a[i] >= 0) 28 sum += a[i]; 29 if(sum == s2) 30 { 31 s2 = sum; 32 loc1 = n; 33 } 34 else 35 break; 36 } 37 if(a[0]>=0) //默认的开头第一个数即为正数 38 { 39 sum=a[0]; 40 for(i=1;i<n;i++) 41 { 42 if(a[i]>=0) 43 { 44 sum+=a[i]; 45 } 46 else 47 { 48 if(sum>=s1) 49 s1=sum; 50 loc=i; 51 if(a[i]<0) 52 sum=0; 53 break; 54 } 55 } 56 57 int sum1=0; 58 for(i=0;i<n;i++) 59 { 60 if(a[i]>=0) 61 { 62 sum1+=a[i]; 63 } 64 else 65 { 66 if(sum1>=s2) 67 { 68 s2=sum1; 69 loc1=i; 70 } 71 if(a[i]<0) 72 sum1=0; 73 } 74 } 75 int s3=0,loc2=0; 76 if(a[n-1]>=0) 77 { 78 sum=a[n-1]; 79 for(i=n-2;i>=0;i--) 80 { 81 if(a[i]>=0) 82 { 83 sum+=a[i]; 84 } 85 else{ 86 s3=sum; 87 loc2=i; 88 break;} 89 } 90 } 91 int s4=s1+s3; 92 if(s2>=s4) 93 { 94 maxS = s2; 95 maxShou = 0; 96 for(i=0;i<loc1;i++) 97 { 98 if(a[i]>0) 99 { 100 maxWei = i; 101 } 102 else 103 break; 104 } 105 /* 106 System.out.print("最大子数组和为:"+s2); 107 System.out.println(); 108 System.out.println("子数组为:"); 109 for(i=0;i<loc1;i++) 110 { 111 if(a[i]>0) 112 { 113 System.out.print(a[i]+" "); 114 } 115 else 116 break; 117 } 118 */ 119 } 120 else 121 { 122 maxS = s4; 123 maxShou = loc2 + 1; 124 maxWei = loc - 1; 125 /* 126 System.out.print("最大子数组和为:"+s4); 127 System.out.println(); 128 System.out.println("子数组为:"); 129 for(i=0;i<loc;i++) 130 { 131 System.out.print(a[i]+" "); 132 } 133 for(i=n-1;i>loc2;i--) 134 { 135 System.out.print(a[i]+" "); 136 } 137 */ 138 } 139 } 140 else //默认的开头第一个数为负数 141 { 142 sum=0; 143 for(i=0;i<n;i++) 144 { 145 if(a[i]>=0) 146 { 147 sum+=a[i]; 148 if(i==n-1&&sum>s1) 149 s1=sum; 150 loc=i; 151 } 152 else 153 { 154 if(sum>=s1) 155 { 156 s1=sum; 157 158 } 159 if(a[i]<0) 160 sum=0; 161 } 162 } 163 maxS = s1; 164 maxWei = loc; 165 for(i=loc;i>=0;i--) 166 { 167 if(a[i]>0) 168 { 169 maxShou = i; 170 } 171 else 172 break; 173 } 174 /* 175 System.out.println("lovc"+loc); 176 System.out.print("最大子数组和为:"+s1); 177 System.out.println(); 178 for(i=loc;i>=0;i--) 179 { 180 if(a[i]>0) 181 { 182 System.out.print(a[i]+" "); 183 } 184 else 185 break; 186 } 187 */ 188 } 189 } 190 else if(x == false) //没有正数的情况下 191 { 192 int t = a[0]; 193 for(i = 1;i < n;i++) 194 { 195 if(a[i] > t) 196 { 197 t = a[i]; 198 maxShou = i; 199 maxWei = i; 200 } 201 } 202 maxS = t; 203 /* 204 System.out.print("最大子数组和为:"+t); 205 System.out.println(); 206 System.out.println("子数组为:"); 207 System.out.print(t); 208 */ 209 } 210 } 211 public int getmaxS(){ 212 return maxS; 213 } 214 public int getmaxShou(){ 215 return maxShou; 216 } 217 public int getmaxWei(){ 218 return maxWei; 219 } 220 } 221 //环形二维数组求最大子数组 222 package erwei; 223 224 import java.util.*; 225 226 public class twoArray extends oneArray{ 227 228 public static void main(String[] args) { 229 // TODO Auto-generated method stub 230 231 Scanner sc = new Scanner(System.in); 232 233 int max,min,numL,numR; 234 int i,j,t; 235 int shouL,shouR,weiL,weiR,maxTwo; 236 237 System.out.println("请输入二维数组的行数和列数:"); 238 numL = sc.nextInt(); 239 numR = sc.nextInt(); 240 241 System.out.println("请输入数组元素取值范围(保证前一个值小于后一个值):"); 242 min = sc.nextInt(); 243 max = sc.nextInt(); 244 245 int[][] twoArray1 = new int[numL][numR]; 246 int[] oneArray1 = new int [numR]; 247 int LTop; 248 249 System.out.println("该二维数组为:"); //生成随机二维数组 250 for(i = 0;i < numL;i++) 251 for(j = 0;j < numR;j++){ 252 twoArray1[i][j] = min + (int)(Math.random()*(max - min)); 253 System.out.print(twoArray1[i][j] + " "); 254 if(j == numR - 1){ 255 System.out.println(); 256 } 257 } 258 259 maxTwo = twoArray1[0][0]; 260 shouL = 0; 261 shouR = 0; 262 weiL = 0; 263 weiR = 0; 264 265 for(i = 0;i < numR;i++){ //一维数组赋初值 266 oneArray1[i] = 0; 267 } 268 System.out.println(); 269 oneArray one = new oneArray(); 270 for(LTop = 0;LTop < numL;LTop++){ //二维数组合并为一维数组 271 for(i = LTop;i < numL;i++){ 272 for(j = 0;j < numR;j++){ 273 oneArray1[j] += twoArray1[i][j]; 274 } 275 one.getMax(oneArray1, numR); 276 if(one.getmaxS() > maxTwo){ 277 maxTwo = one.getmaxS(); 278 shouL = LTop; 279 shouR = one.getmaxShou(); 280 weiL = i; 281 weiR = one.getmaxWei(); 282 } 283 } 284 for(t = 0;t < numR;t++){ 285 oneArray1[t] = 0; 286 } 287 } 288 289 System.out.println("环形二维数组最大子数组和为:"); 290 System.out.println(maxTwo); 291 System.out.println("该最大子数组为:"); 292 if(shouR > weiR){ 293 for(i = shouL;i <= weiL;i++){ 294 for(j = shouR;j < numR;j++){ 295 System.out.print(twoArray1[i][j] + " "); 296 } 297 for(j = 0;j <= weiR;j++){ 298 System.out.print(twoArray1[i][j] + " "); 299 } 300 System.out.println(); 301 } 302 } 303 else{ 304 for(i = shouL;i <= weiL;i++){ 305 for(j = shouR;j <= weiR;j++){ 306 System.out.print(twoArray1[i][j] + " "); 307 } 308 System.out.println(); 309 } 310 } 311 312 sc.close(); 313 } 314 315 }
三、设计过程
在实现过程中,一开始使用接口,后来使用另建一个新类来调用,类的使用还更熟练一些。
编写的过程中大概有一个半小时卡在了将二维转化为一维数组的过程。一开始的想法是:
1)设出首行和末行,首行与末行在同一位置;
2)先保持首行不变,求出首行到末行相加后的一维数组;
3)末行依次递增到最后一行;
4)当末行递增到最后一行后,首行向下一行,末行再回到与首行相同的位置,重复2),3)直到首行也到达最后一行。
可怎么也求不出正确相加的一维数组,突然想到为什么要让末行变来变去,只要保持首行不变,末行一直加到最后一行,只不过每加一行就可以向一维数组传递,加到最后一行后就让首行向下移动即可,首行一直移动到最后一行。
四、实验结果
非负:
有正有负:
全负:
五、结对成员
刘双渤、刘洪阳。
思路:刘双渤、刘洪阳。
编程:刘双渤、刘洪阳。