zoukankan      html  css  js  c++  java
  • 返回一个整数数组中最大子数组的和 (非环状 和环状)

    题目要求:

    输入一个整形数组,数组里有正数也有负数。
    数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
    求所有子数组的和的最大值。

    要求数组从文件读取。
    如果输入的数组很大, 并且有很多大的数字, 就会产生比较大的结果 (考虑一下数的溢出), 请保证你的程序能正常输出。
    另外, 如果输入文件的参数有错误, 这个程序应该能正常退出, 并显示相应的错误信息。 任何输入错误都不能导致你的程序崩溃。

    设计思路:

    1. 首先理解题目,当时在课堂上老师给出题目的时候,我对于题目的理解有很大的偏差,结果对题目的解决造成很大困扰。

    题目的意思是找到连续的子数组的和的最大值,这些子数组的意思是该数组所能构成的所有连续子数组,可以随意的任取。

    举例子:

    数组  {5,8,-6,7,10}

    该数组的连续或单个子数组可以为  {5,8},{8,-6,7},{10}等 

    而我却理解为把数组随机分解,然后找寻子数组的最大值

    如分解为:

    {5,8},{-6},{7,10};  

    2.解决思路

    解决非环状子数组最大值:

    首先找到数组的第二个元素,将其与前一个元素相加进行比较,如果在该位置上的原有元素的值 比两个元素的值之和小,则将该位置的元素替代为两个元素的和,否则元素不变,

    遍历该数组,执行该操作,如果前两个元素之和大于该元素,则替换,若后一个与现在值之和仍旧与前面一样,则这是可以构成一个至少三个连续元素的子数组。

    如此便可以找到

    例如:

    {5 ,-6, 7, -5, 4} 

    第一次(第二个开始): 后一个为负数,前一个为正数 相加必大于原来的值

    {5,-6+5=-1,7,-5,4}

    第二次:  前一个和后一个相加不符合条件 不执行操作

    {5,-1,7,-5,4}

    第三次:  符合条件 执行操作

    {5,-1,7,-5+7=2,4}

    第四次:  符号操作,执行操作

    {5,-1,7,2,2+4=6}

    如此,每一个位置都代表一种子数组的和,找寻最大值即可

    第二种解决环状 参考 地址如下:

    https://blog.csdn.net/weixin_34364071/article/details/93782011

    首先要解决的是如何让收尾相加可以实现? 

    在我的参考当中,是每次执行的时候都将首位元素调动到数组的最后位置。余下的就是防止在一个子数组当中让一个元素出现两次,造成多次相加。

    对于该方法就是执行三次循环控制位置,避免元素的多次相加

    3. 异常处理

    创建一个继承自Exception 的自定义异常类,将除整数之外的其他情况排除,让文件读取时只能读取整数,当出现除整数之外的其他符号时,终止程序,并提升错误信息。

    4. 目前刚刚完成程序,有点一叶障目的感觉,检查程序都会不自觉的按照程序设定能够运行的方式检验。不能发现错误,希望各位如果发现问题,请为我指正。

    运行结果如下:

    实现代码如下:

    package Test;
    
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileReader;
    import java.util.Scanner;
    
    
    
    public class ReadShuZuMax {
        
            static Scanner sc=null;
            
            static int check(String c) throws MyException {
                if(!c.matches("^\-?[0-9]+$")) {  //匹配所有的整数
                    throw new MyException("数据异常,请重新录入!");
                }
                
                return Integer.valueOf(c);
            }
            
            public static void main(String[] args) throws Exception {
                
                BufferedReader bf=new BufferedReader(new FileReader(new File("C://Users//cuixingyu//Desktop//number.txt")));
                String textline="";
                String str="";
                
                while(((textline=bf.readLine())!=null)) {
                    str+=textline;
                }
                System.out.println(str);
                
                String[] numbers=str.split(" ");
                int a[]=new int[numbers.length];
                int b[]=new int[numbers.length];
                for(int i=0;i<numbers.length;i++) {
                    a[i]=check(numbers[i]);
                    b[i]=check(numbers[i]);
                }
                
                int n=a.length;
                for(int i=1;i<n;i++) {    
                    if(a[i]+a[i-1]>a[i]) {
                        a[i]=a[i]+a[i-1];
                    }
                }
                
                int max=a[0];
                for(int i=1;i<n;i++) {     //找到最大的数组和
                    max=Math.max(max, a[i]);
                }
                System.out.println("最大的子数组和(非环状):");
                System.out.println(max);
                
                int max1=0;
                for(int x=0;x<n;x++) {        //每次循环把第一个数移动到数组最后的位置,便于环形相加
                    int w=b[0];
                    for(int i=0;i<n-1;i++) {
                        b[i]=b[i+1];
                    }
                    b[n-1]=w;
                    
                    
                    for(int y=0;y<n;y++) {       //最外层控制子数组的头
                        
                        for(int z=y;z<=n;z++) {   //中层控制子数组的尾
                            
                            int sum=0;
                            for(int u=y;u<z;u++) {   //内层循环从头加到尾
                                
                                sum=sum+b[u];
                                
                                if(max1<=sum) {   //把最大子数组的和赋值给max1
                                    max1=sum;
                                }
                            }
                        }
                        
                    }
                    
                    
                }
                System.out.println("最大的子数组和(环状):");
                System.out.println(max1);
                
            }
        
    
    }

    除此之外还有一个自定义的异常类

    package Test;
    
    public class MyException extends Exception{
        
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
    
        public MyException(String message) {
            super(message);
        }
    }
  • 相关阅读:
    [BZOJ4698][SDOI2008]Sandy的卡片(后缀自动机)
    [NOI2015]小园丁与老司机(DP+上下界最小流)
    [BZOJ2007][NOI2010]海拔(对偶图最短路)
    [NOI2018]屠龙勇士(exCRT)
    [NOI2018]归程(可持久化并查集,Kruskal重构树)
    [BZOJ2823][BZOJ1336][BZOJ1337]最小圆覆盖(随机增量法)
    [BZOJ1069][SCOI2007]最大土地面积(水平扫描法求凸包+旋转卡壳)
    [BZOJ1143][CTSC2008]祭祀river(Dilworth定理+二分图匹配)
    [BZOJ3160]万径人踪灭(FFT+Manacher)
    [NOI2015]寿司晚宴
  • 原文地址:https://www.cnblogs.com/cxy0210/p/12368046.html
Copyright © 2011-2022 走看看