《返回一个整数数组中最大子数组的和》团队合作及第六周学习进度条

团队合作第一棒:输入一个一维整形数组,数组里有正数也有负数。一维数组首尾相接,象个一条首尾相接带子一样。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。
一、设计思想:
  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;
    }
}

五、结果截图:

六、总结:这次的结对合作,的确让我受益匪浅,能够明白思想碰撞的火花的重要性,另外编写程序要有一个清晰的思路,不能提笔就写,盲目没有好下场,所以今后的代码之路一定要慎思笃行,学会和别人合作,并在团队中要发挥作用,从中获取知识。

本次实验由井小普和张贺合作完成,在数组进行循环之后如何处理子数组,并求出最大子数组的和进行了交流。

第六周学习进度条:

原文地址:https://www.cnblogs.com/zhangjiabei/p/6646420.html