《返回一个整数数组中最大子数组的和》团队合作及第六周学习进度条
团队合作第一棒:输入一个一维整形数组,数组里有正数也有负数。一维数组首尾相接,象个一条首尾相接带子一样。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。
一、设计思想:
1.最初,在设计循环数组之前,运用maxsum和maxstart来对遍历最大子数组过程中的最大值进行更新与保存,主要设计思路是:将两个值分别赋予数组的第一个数,然后对所输入的数组的值进行逐次遍历,maxstart进行数组中值的相加,如果maxstart大于maxsum,及时进行更新maxsum的值,如果maxstart的值过小,则将之前的数组中的值进行丢弃,将自己赋为0,加上数组中的下一个值(即直接赋予数组中的下一个数值),重新比较,依次更新,最后获得最大的sum值。
2.老师将要求修改为循环数组后,于是将maxsum设为全局变量,数组扩大了一倍(即将所输入的数组重复导入所定义数组中),增设了一个循环,就是将初始值分别设为数组中的每一个数,然后依次向后循环加上(所设数组长度)个值,原理同上,但时间复杂度变为了平方。
3.要想使得时间复杂度为n,增设了判断数值正负的函数、单个最大值函数,之后沿用以前的思路,问题得以解决。
二、出现的问题:
1.for循环下如果用if来使得max与数组为1,2,3......n的子数组进行比较,n不能确定,所以数组求和遇到问题。于是边求和边比较,子数组的和用一个变量来进行存储,最大值用另一个变量进行存储,收尾相接需要注意子数组的和,否则会超过子数组所应存在的范围。
2.子数组和的数目可能会超过原来数组和的数目,用变量jishu来控制,k记录是第几次超过,超过之后maxstart,jishu重置为0,循环从k+1开始。
3.如果都是负数,maxstart赋初值为0会大于数组本身,单个元素的最大值即为最大子数组。
三、可能的解决方案:
可能的解决办法同上述设计思想与可能遇到的问题。
四、源代码:
(以下第一个源代码的时间复杂度为O(n方))
import java.util.Scanner; public class maxShuZu { public static int maxsum; public static void main(String[] args) { // TODO Auto-generated method stub int i,j; int maxstart; Scanner in=new Scanner(System.in); System.out.println("请输入数组的大小:"); int number=in.nextInt(); int array[]=new int[number*2]; System.out.println("请输入数组的值:"); for(i=0;i<number;i++) { array[i]=in.nextInt(); array[i+number]=array[i]; } maxsum=array[0]; for(j=0;j<number;j++){ maxstart=array[j]; for(i=j+1;i<j+number;i++){ if(maxstart<0){ maxstart=0; } maxstart+=array[i]; if(maxstart>maxsum){ maxsum=maxstart; } } } System.out.println("最大子数组的和为:"+maxsum); in.close(); } }
经过修改,将源代码的时间复杂度改为了O(n)
代码如下:
import java.util.Scanner; public class max { public static int maxsum; public static void main(String[] args) { // TODO Auto-generated method stub int i,j,jishu,k; boolean flag=true;//判正负 int maxstart = 0; Scanner in=new Scanner(System.in); System.out.println("请输入数组的大小:"); int number=in.nextInt(); int array[]=new int[number*2]; System.out.println("请输入数组的值:"); for(i=0;i<number;i++) { array[i]=in.nextInt(); array[i+number]=array[i]; } //---判断数组是否全为负数 flag=Pan(array); if(flag) { maxsum=Max(array); } //--- maxsum=array[0]; jishu=0;//子数组数 k=0;//第几次达到最大数组数 for(j=0;j<2*number-1;j++){ maxstart+=array[j]; jishu++; if((maxstart<0)){ maxstart=0; jishu=0; } if(jishu>number) { if(k<number) { jishu=0; j=k;//经过k++从下一轮开始 maxstart=0; k++; } } if(maxstart>maxsum){ maxsum=maxstart; } } System.out.println("数组:"); for(i=0;i<number*2-1;i++) { System.out.print(array[i]+" "); } System.out.println("最大子数组的和为:"+maxsum); in.close(); } public static boolean Pan(int[] array) { boolean flag=true; for(int i=0;i<array.length;i++) { if(array[i]>0) { flag=false; break; } } return flag; } public static int Max(int[] array) { int max=array[0]; for(int i=0;i<array.length;i++) { if(array[i]>max) max=array[i]; } return max; } }
之后又对代码进行了完善,如下:
import java.util.Scanner; public class maxArray { public static void main(String[] args) { // TODO Auto-generated method stub int i=0,maxsum=0; boolean flag=true; Scanner in=new Scanner(System.in); System.out.println("请输入数组的大小:"); int number=in.nextInt(); int array[]=new int[number*2-1]; System.out.println("请输入数组的值:"); for(i=0;i<number;i++) { array[i]=in.nextInt(); if(i<number-1) { array[i+number]=array[i]; } } flag=Pan(array); if(flag==true) { maxsum=Max(array); } else { maxsum=sumMax(array,number); } System.out.println("数组:"); for(i=0;i<array.length;i++) { System.out.print(array[i]+" "); } System.out.println("最大子数组的和为:"+maxsum); in.close(); } //-----最大子数组的和 public static int sumMax(int[] array,int number) { int i,jishu=0,k=0;//jishu 控制子数组个数,k记录第几次到达最大数组数 int maxstart=0;//子数组和的初始值 int maxsum=array[0];//初始值 for(i=0;i<array.length;i++){ maxstart+=array[i]; jishu++; if((maxstart<0)){ { maxstart=0; jishu=0; } } if(jishu>number) { if(k<number) { jishu=0; i=k;//经过k++从下一轮开始 maxstart=0; k++; } } if(maxstart>maxsum){ maxsum=maxstart; } } return maxsum; } //----判断数组是否全为负数,true 正数,false 负数 public static boolean Pan(int[] array) { boolean flag=true; for(int i=0;i<array.length;i++) { if(array[i]>0) { flag=false; } } return flag; } //------单个最大值 public static int Max(int[] array) { int max=array[0]; for(int i=0;i<array.length;i++) { if(array[i]>max) { max=array[i]; } } return max; } }
五、结果截图:
六、总结:这次的结对合作,的确让我受益匪浅,能够明白思想碰撞的火花的重要性,另外编写程序要有一个清晰的思路,不能提笔就写,盲目没有好下场,所以今后的代码之路一定要慎思笃行,学会和别人合作,并在团队中要发挥作用,从中获取知识。
本次实验由井小普和张贺合作完成,在数组进行循环之后如何处理子数组,并求出最大子数组的和进行了交流。
第六周学习进度条: