题目要求:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。
要求数组从文件读取。
如果输入的数组很大, 并且有很多大的数字, 就会产生比较大的结果 (考虑一下数的溢出), 请保证你的程序能正常输出。
另外, 如果输入文件的参数有错误, 这个程序应该能正常退出, 并显示相应的错误信息。 任何输入错误都不能导致你的程序崩溃。
设计思路:
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); } }