标签:图片 stack class 答案 boolean 告诉 cli line scanner
提示:图片如果看不全右键打开图片
3月7号
我的想法:
a数组由正负数组成,创建一个数组,对应已知的a整数数组,正为1负为-1,一一对应,创建一个只含1与-1的数组称为b,然后a对应b创建数组c,对应b邻近的都为1和邻近都为-1的a中相应的整数数加起来变为c数组,c数组有前面的方法创建b1,
此时b1必为1与-1相间的数组,我代码的量就做到这里。
接下来的思路:
此时的:数组b1假设为(1,-1,1,-1,1)
3月8号:
查阅了《算法导论》这本书,书中第38页介绍的这个问题,书上的讲得是分而治之的方法。
但并不是O(n),但是课后习题4.15提出了解决方案:
3月9号晚:
这个方法一开始是看不懂的,然后我在网上查到了源码答案,然后琢磨了20多分钟终于弄明白了。
以图片的形式表示出来:
我在从数学的角度解释一下,把整数数组可以分为有限个块(因为数组是有限的),求有限个块的各自的和sum,然后最大和子数组是这些有限个块中一员;
这个最大和子数组也是由有限个块组成的,但是它有一个不变也是最重要的特征:它是由一个sum为连续的非负数的最大块和一个非负数的数字组合成的,或者只是一个非负数。
具体方法讲解:上面图片应该就是基本的步骤
设置一个int max纪录当前已知最大的,从数组中从左到右(从右到左一样)依次选出元素放入一个块中,设置sum为块中整数和(初始为0),max最初设为(二声)什么无所谓,就设为0。(有一种可以存在数组中都为非正数的情况,需要特殊求解,找出最小非正数就为最大和子数组)
从数组中取出第一个数字,(①②不是步骤而是情况,如果是步骤我会指出。而且后面的正数情况包括此数为0,也就是说我把此数为0的情况归为此数为正数的情况,即使把0的情况归給负数情况也一样,不影响)
实例步骤解析
第一步:
①为正数,加入块中,sum=sum+此数 此时块中元素有一个正数,sum>0。
②为负数,加入块中,sum=sum+此数,sum<0了,重置块,此时块中无元素,sum=0。为什么呢?因为我们上面所说的特征,此时不满足这个特征。
判断此时sum与max,如果sum大于max,max=sum(每一步之后都得判断)
第二步:
①为正数,加入块中,sum=sum+此数 当第一步为①此时块中元素有俩个正数,sum>0;当第一步为②此时块中元素只有一个正数,sum>0。
②为负数,加入块中,sum=sum+此数,当第一步是②sum<0了,重置块,此时块中无元素;sum=0,当第一步为①时,此时sum=sum+此数,sum>0,sum不变,sum<0时sum=0。
判断此时sum与max,如果sum大于max,max=sum
第三步:
重复第二步类似的步骤
.
.
..
.
直到最后一个元素进入。
此时输出max就是最大和子数组的和。
它的特征:它是由一个sum为连续的非负数的最大块和一个非负数的数字组合成的,或者只是一个非负数。
说真的我感觉我自己也说不明白,我不会讲,但是我自己明白了。但是我告诉你这个特征,这个特征我自己总结的,觉得这个特征就是解题所在。
代码:
1 int max_int_Array(int a[]) 2 { 3 int sum=0; 4 int max=0; 5 for(int i=0;i<a.length;i++) 6 { 7 sum=sum+a[i]; 8 if(sum<0) 9 { 10 sum=0; 11 } 12 if(sum>max) 13 { 14 max=sum; 15 } 16 } 17 if(sum==0) 18 { 19 max=a[0]; 20 for(int i=1;i<5;i++) 21 { 22 if(max<a[i]) 23 { 24 max=a[i]; 25 } 26 } 27 } 28 return max; 29 30 }
在网上也可以找到这个代码,这是我写的。我就是借鉴的《算法导论》习题4.15的答案,不看答案我看不懂他那个方法,但是我发现最大和子数组的特征时,我就看懂了。
总结:
上课时的思路就是错的,没有找到解题的关键(最大和子数组的特征),后来开窍了,弄明白了。
使用以前学习过Integer类,能够处理大数。把原先的返回值改为Intger,把里面的sum,max定义为Intger。
文件读取在写一个函数把文件中数字存入Integer数组或者创建一个Integer_(类名字自定)类里面有一个元素Integer,然后使用List<INteger_>定义一个List数组来操作。
今日错误txt读取数字时程序一直运行,我都不知道哪出错。
3月10号早,上述问题已解决。
判断是否为数字返回错误的函数:
1 boolean isNumeric00(String str) 2 { 3 try{ 4 Integer.parseInt(str); 5 return true; 6 }catch(NumberFormatException e) 7 { 8 System.err.println("异常:\"" + str + "\"不是数字/整数..."); 9 return false; 10 } 11 }
文件读取函数:
1 ArrayList<String> wenjian(String b) 2 { 3 ArrayList<String> list = new ArrayList<String>(); 4 boolean flag=true; 5 try // 建立一个对象,它把文件内容转成计算机能读懂的语言 6 { 7 Scanner shuru = new Scanner(new BufferedReader(new FileReader(b))); 8 String a; 9 //网友推荐更加简洁的写法 10 while ((shuru.hasNext()) ) { 11 // 一次读入一行数据 12 a=shuru.next(); 13 if(isNumeric00(a)) 14 { 15 list.add(a); 16 } 17 else 18 { 19 flag=false; 20 } 21 22 } 23 shuru.close(); 24 } catch (IOException e) { 25 26 e.printStackTrace(); 27 } 28 if(flag==true) 29 { 30 return list; 31 } 32 else 33 { 34 System.err.println("文件格式有错误"); 35 return null; 36 } 37 38 }
将String数组转化为Integer数组:
1 ArrayList<Integer> String_To_Integer(ArrayList<String> list) 2 { 3 ArrayList<Integer> list1 = new ArrayList<Integer>(); 4 for(int i=0;i<list.size();i++) 5 { 6 Integer integer =new Integer(list.get(i)); 7 list1.add(integer); 8 } 9 return list1; 10 11 }
计算最大和整数组:
Integer max_int_Array(ArrayList<Integer> b) { Integer sum=0; Integer max=0; for(int i=0;i<b.size();i++) { sum=sum+b.get(i); if(sum<0) { sum=0; } if(sum>max) { max=sum; } } if(sum==0) { max=b.get(0); for(int i=1;i<b.size();i++) { if(max<b.get(i)) { max=b.get(i); } } } return max; }
结果如下:
总结:
把问题分部,第一步读取,然后读取中得判断读出来的是不是都是数字(查阅后引用的捕捉异常的函数),第二步把读取出的String转化为Integer,第三步求最大和数组的和。
分析问题:
如果是二维数组,那么它的最大和子数组必是一个规则的长方形或特殊长方形(正方形)。特征:它肯定是一个非负数的长方形或者一个非负数的连续最大长方形加上一个非负数的偏小非负数的长方形。
把每一行看成一个块的话,那么就成了一个只有块的一维数组。在块中由上面的方法处理,找出每个块的最大和子数组,然后根据这几个最大和子数组来上下加入块来求取二维数组的最大和子数组。
分步:第一步读取文件,第二步转化,第三步求最大和子数组。
标签:图片 stack class 答案 boolean 告诉 cli line scanner
原文地址:https://www.cnblogs.com/gonT-iL-evoL-I/p/10492931.html