环形数组求最大子数组之和:
实验要求:
随机产生一个整形数组,假设首尾相连为环形,求其相连的字数组的和,并输出子数组的元素。
设计思路:
因为是环形,所以要考虑自设的头尾的情况,在此分为两大类考虑,一种为数组中存在正数情况,一种为全部为负数的情况;
在存在正数的情况中又可分为三种情况,一种为全部为正数的情况,一种为自设的头元素为正数,最后一种为自设的头元素为负数。根据这几种情况分类进行实现。
在实现过程中,对数组元素从头到尾进行遍历,如果遇到正数即用和相加,直到相邻的下一个为负数,即存放目前该最大数组和,最后几个相邻的正数的和相比较,求出最大的。
特殊情况为自设的头元素为正数,即首先存放头元素数组的和,然后分情况考虑尾数组是否为正,若为证即存放尾数组和,最后首尾数组和相加,即为相连的数组的和。
代码实现:
package 环形子数组求和; import java.util.Scanner; public class hx { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Scanner A=new Scanner(System.in); System.out.println("请输入数组长度:"); int n=A.nextInt(); System.out.println("请输入数组数值范围:"); int N = A.nextInt(); int M = A.nextInt(); int a[] = new int[n]; int b[][] = new int[n][n]; int i; System.out.println("数组为:"); for(i=0;i<n;i++) { a[i] = N + (int)(Math.random()*(M-N)); System.out.print(a[i]+" "); } System.out.println(); boolean x = false; for(i=0;i<n;i++) { if(a[i]>=0) { x = true; break; } } int sum=0,s1=0,s2=0,loc=0,loc1=0; if(x == true) //有正数的情况下 { for(i=0;i<n;i++) //全部为正数的情况下 { s2+=a[i]; if(a[i]>=0) sum+=a[i]; if(sum==s2) { s2=sum; loc1=n; } else break; } if(a[0]>=0) //默认的开头第一个数即为正数 { sum=a[0]; for(i=1;i<n;i++) { if(a[i]>=0) { sum+=a[i]; } else { if(sum>=s1) s1=sum; loc=i; if(a[i]<0) sum=0; break; } } int sum1=0; for(i=0;i<n;i++) { if(a[i]>=0) { sum1+=a[i]; } else { if(sum1>=s2) { s2=sum1; loc1=i; } if(a[i]<0) sum1=0; } } int s3=0,loc2=0; if(a[n-1]>=0) { sum=a[n-1]; for(i=n-2;i>=0;i--) { if(a[i]>=0) { sum+=a[i]; } else{ s3=sum; loc2=i; break;} } } //System.out.print(":s"+s1+" "+s2+" "+s3); //输出结果测试中间过程是否正确 // System.out.print(":"+loc+" "+loc1+" "+loc2); int s4=s1+s3; if(s2>=s4) { System.out.print("最大子数组和为:"+s2); System.out.println(); System.out.println("子数组为:"); for(i=0;i<loc1;i++) { if(a[i]>0) { System.out.print(a[i]+" "); } else break; } } else { System.out.print("最大子数组和为:"+s4); System.out.println(); System.out.println("子数组为:"); for(i=0;i<loc;i++) { System.out.print(a[i]+" "); } for(i=n-1;i>loc2;i--) { System.out.print(a[i]+" "); } } } else //默认的开头第一个数为负数 { sum=0; for(i=0;i<n;i++) { if(a[i]>=0) { sum+=a[i]; if(i==n-1&&sum>s1) s1=sum; loc=i; } else { if(sum>=s1) { s1=sum; } if(a[i]<0) sum=0; } } System.out.println("lovc"+loc); System.out.print("最大子数组和为:"+s1); System.out.println(); System.out.println("子数组为:"); for(i=loc;i>=0;i--) { if(a[i]>0) { System.out.print(a[i]+" "); } else break; } } } else if(x == false) //没有正数的情况下 { int t=a[0]; for(i=1;i<n;i++) { if(a[i]>t) { t=a[i]; } } System.out.print("最大子数组和为:"+t); System.out.println(); System.out.println("子数组为:"); System.out.print(t); } } }
实验结果:
结果分析:
在实验过程中产生随机数及构思过程较为简单,但在实现过程中分情况还遇到不少情况,其中定义一个boolean x = false;类型,在if语句中用一个等号并不报错,但运行过程中直接跳过,用两个等号即可运行。
在用sum存放数组之和时,因为有循环,所以总是变化,而且一开始存放的为所有的正数的和,并不连续,加一个else语句后再存放和即可存放最大,break很好的处理在遇到负数时跳出的情况。
在输出数组元素时用一个代表当最大的sum时的数组位置,在最后循环输出符合要求的元素即可。
结对实现:
刘洪阳、刘双渤:共同讨论,共同研究实现方法,各自完成代码部分,然后相比对,找不足相互吸取优点。