题目集4~6的总结性Blog
(1)前言:总结三次题目集的知识点、题量、难度等情况
题目集四:
第一题:7-1 水文数据校验及处理
这一题主要是对一大批数据进行提取,分割后对数据进行处理,主要用到的是正则表达式。
例如题目中要求输入这样的一串数据:
2015/8/2 4:00|133.8400|133.070|1.11/1.21|75.780
2015/8/2 6:00|133.840|133.080|11.11/1.11|72.8a0
2015/8/2 8:00|133.830|133.070|1.11/1.11|73.890
2015/8/2 10:00|133.820|133.080|1.11/1.11|74.380
exit
首先我写之前就需要对它进行分析:这串数据有若干行,但是每行输入的数据模式是一样的,都先是日期时间,然后是目标水位、实际水位、开度,最后以exit结束输入,这些数据规律的分析就有利于我们去想出一个合理的方法去分割利用这些数据。
至于分割数据,就用到了正则表达式,比如我要在这些数据里面匹配到实际开度:就需要我写出相应的表达式:"(([1-9]|[1-9][0])(\\.[0-9]{2}))"
另外,还可能需要用到这些
1、append():
s.append("Runoob..!");在字符串s后面添加字符串"Runoob.."
2、insert(:
sb.insert(8, "Java");在字符串s的第八个位置(!前面)插入字符串"Java"
3、delete(int start, int end)的用法:
sb.delete(5,8);删除位置5-8的字符
Pattern p = Pattern.compile("(([1-9]|[1-9][0])(\\.[0-9]{2}))");声明一个p对象,
等等

还有,题目中的要求输入输出的格式也需要仔细考虑。
- 测量时间:格式为“年/月/日 时:分”,其中年份取值范围为[1,9999],“月”与“日”为一位数时之前不加“0”,日期与时间之间有一个空格,“时”与“分”之间采用冒号分隔(英文半角),“时”为一位数时之前不加“0”,“分”始终保持两位,且始终为“00”。注意:“时”数必须是24小时进制中的偶数值
- 难度:极难,(我反正写地好费劲,因为当时正则表达式还非常陌生,我要一边学正则表达式一边做题目,举步维艰)
第二题:7-2 日期问题面向对象设计(聚合一)
这题主要是输入数据求日期的前n天,或者求日期的后n天,或者输入两个日期,计算两个日期之间相差的天数。
例如,有下面这三种输入格式:
- 1 year month day n //测试输入日期的下n天
- 2 year month day n //测试输入日期的前n天
- 3 year1 month1 day1 year2 month2 day2 //测试两个日期之间相差的天数
主要是类的设计和传参方式,此外还需要基础的判断,比如在所有日期问题前面,都存在着平年和闰年的判断,这个可以在DateUtil类下面写一个方法,专门用作判断某一年是闰年还是平年,平年和闰年二月份的天数也不同,在判断完是平年还是闰年后,对该年的二月份天数进行赋值,我的处理方法就是,先建立一个存储12个月平年的每个月的天数,如果判断这一年是闰年,那么就把二月份的天数改成29天,代码:
int[] allmonth = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};、
if((year % 4 == 0 && year % 100 != 0)||year % 400 == 0) {
allmonth[2] = 29;
}
还有一个判断就是检查输入数据的合法性,除了题目中规定的年份区域,还有本来就存在的日期规律,一年最多只有12个月,输入的月份后,天数不能超过这个月的最大值,比如你输入的是4月,后买你紧接着输入的天数就不能超过30天,最小也肯定不能小于1,还有一个判断就是,如果输入的这一年是闰年,那么二月份就有29天,所以输入年份之后,再输入的月份是二月份,那么天数就可以输入最大为29,即使输入的天数是29,那也是合法的,那如果是平年,按照刚刚的输入,就不能超过28天,超过了就需要进行提示了。
然后就是计算前n天的处理方式了,前n天也就是回到过去,就是在这个日期减,所以需要用到一个循环,每减一次就循环一次,共循环n次,循环体内也需要进行判断,判断该月的天数是不是小于1了,要是小于1的话,月份就进行自减1,天数变为前一个月的最大天数,如果减下去月份小于1了,那么就年份自减1,月份变为12月,依次循环。
计算后n天的方式也是类似,只不过是回到未来,不断循环自加,相应地月份和年份满足条件后也需要相应变动!
那么接下来就剩下求两个日期之间相差的天数了,这里也有很多实现方法,但是有一个方法最好理解了,就是让较大地那个日期在循环下减,并记录减的次数,直到和那个较小地日期相等,所以,要解决这个实现方式,就需要写一个比较输入的两个日期大小的方法,这样就能获得较大的那个日期进行减操作,这样才能减到与另一个较小的日期相等的那一步,然后还要写一个判断两个日期是否相等的方法,在减n天后,看是否相等,所以每次循环都要判断,都要用到,这个处理方式比较容易理解,但是,它有一个缺点,就是效率不高,循环很多,运行时间很长,所以有待改进。
类图如下:

难度:难(需要想到合适的方式去实现,因为之前也没有处理过这样的问题)
第三题:7-3 图形继承
编写程序,实现图形类的继承,并定义相应类对象并进行测试。
这题就是考察继承的语法知识,需要理解继承中,子类和父类的关系,以及继承的规则,比如,父类的构造方法不能被子类继承,私有变量也不能被继承,在继承中,子类可以重写父类的方法……诸如此类的语法规则。
那么在这一题中,需要我们定义一个父类Shape,下面的子类是各种平面图形,用来计算周长、面积,
- 类Shape,无属性,有一个返回0.0的求图形面积的公有方法
public double getArea();//求图形面积 - 类Circle,继承自Shape,有一个私有实型的属性radius(半径),重写父类继承来的求面积方法,求圆的面积
- 类Rectangle,继承自Shape,有两个私有实型属性width和length,重写父类继承来的求面积方法,求矩形的面积
- 类Ball,继承自Circle,其属性从父类继承,重写父类求面积方法,求球表面积,此外,定义一求球体积的方法
public double getVolume();//求球体积 - 类Box,继承自Rectangle,除从父类继承的属性外,再定义一个属性height,重写父类继承来的求面积方法,求立方体表面积,此外,定义一求立方体体积的方法
public double getVolume();//求立方体体积
其实只要知道了这些继承关系,这道题是不算难的。
难度:易
题目集五:
第一题:7-1 找出最长的单词-hebust
输入若干个字符串,以空格分开。
这道题很简单,只需要用到.split()就能写出来,就是在输入完后,按照“”空格分割标志分割字符串,定义一个数组,然后把分隔开来的字符子串按顺序储存在一个数组中,最后在数组内,将每个进行后排序就可以了,接收输入的数据,然后分割的代码如下
String vocabulary = input.nextLine();
String[] arr = vocabulary.split(" ");
这里我是保存在数组 arr [ ] 中
难度:极易
第二题:7-2 合并两个有序数组为新的有序数组
首先输入第一个数组的数据个数后输入第一个数组按升序排序的数据,然后再输入第二个数组的数据个数,最后输入第二个数据按升序排序的数据。数据之间用一个或多个空格或回车符分隔。
我是定义两个数组,先输入第一个数组大小,然后挨个输入数组元素,紧接着输入第二个数组,然后定义第三个数组,长度是前面两个数组之和,然后第三个数组里面的元素就是前两个数组里面的元素,最后对第三个数组进行排序,排序可以用冒泡排序、选择排序、插入排序。最后输出就可以了。
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] arr1 = new int[n];
for(int i = 0;i<n;i++){
arr1[i] = in.nextInt();
}
int m = in.nextInt();
int[] arr2 = new int[m];
for(int j = 0;j<m;j++){
arr2[j] = in.nextInt();
}
int sum = m + n;
int[] arr=new int[sum];
for(int k=0;k<n;k++)
{
arr[k]=arr1[k];
}
难度:极易
第三题:7-3 对整型数据排序
题目要求:
- 第一行输入待排序数组长度;
- 第二行输入待排序数据(均为整型数据),数据之间使用一个或多个空格分隔;
- 第三行输入所选择的算法,其中:
- 插入排序
- 选择排序
- 冒泡排序
- 因为题目中并给出了主函数的代码,我只需要把插入排序,选择排序,冒泡排序完善就好了。
考察内容就是这三种排序方式。
难度:极易。
第四题 :7-4 统计Java程序中关键词的出现次数
编写程序统计一个输入的Java源码中关键字(区分大小写)出现的次数。说明如下:
- Java中共有53个关键字(自行百度)
- 从键盘输入一段源码,统计这段源码中出现的关键字的数量
- 注释中出现的关键字不用统计
- 字符串中出现的关键字不用统计
- 统计出的关键字及数量按照关键字升序进行排序输出
- 未输入源码则认为输入非法
这一题我是先处理整个字符串,就是先删除注释的内容,还有代码里面的字符串内容,因为这里面的关键字是不用统计出现的次数的,然后处理后通过toString转化成字符串,这就是处理后的吧字符串,下面要统计的关键字就是这个字符串里面了,这里就要用到ArraryList了,把出现的关键字添加到里面,然后通过循环统计这个数组里面的关键字,最后排序后输出就行了,有些地方字符串的提取的正则表达式需要编辑,部分正则表达式如下,按照这样的方式去匹配。
Pattern p=Pattern.compile("\"(.*?)\"");
Matcher m=p.matcher(sumper3);
while(m.find()){
sumper3=sumper3.replace(m.group()," ");
p=Pattern.compile("\"(.*?)\"");
m=p.matcher(sumper3);
}
p=Pattern.compile("/\\**(.*?)/");
这题也主要是正则表达式的使用,正则表达式的编辑有难度,还有就是map集合的使用,需要自己查阅资料,我还是运用的不太熟练,这道题写了很久,中途也遇到了很多麻烦,经过了很久的修改,我还是有一个点没有通过。
改进方法:还需要学习这个map集合的使用,我还是非常不熟练,还有正则表达式,我发现我对于正则表达式的编辑还非常不熟练,特别是如果需要匹配更复杂的字符串,我会更困难,所以还是需要我多练习!
难度:较难。
第五题 :7-5 日期问题面向对象设计(聚合二)
这道题和7-2 日期问题面向对象设计(聚合一)很相似,都很难写。
题目集六:
第一题:7-1 正则表达式训练-QQ号校验
题目要求:
校验键盘输入的 QQ 号是否合格,判定合格的条件如下:
- 要求必须是 5-15 位;
- 0 不能开头;
- 必须都是数字;
题目的要求直接可以在正则表达式上体现,主要就是匹配一串数字,不能包括其他字符,也不能是字母,并且匹配的QQ号码长度不是固定的,长度在5-15范围之间,QQ号不能以数字0开头,
所以我用到了正则表达式中的 “ ^ ” 和 “ ¥ ”符号规定了开头和结尾必须是匹配数字 ,我写的正则表达式如下:
String match = "^[1-9]{1}[0-9]{4,14}";
匹配这个很简单,所以正则表达式书写起来也很简单。
最后在代码结尾再添加一个判断就可以了,这题就做完了。
难度:极易
第二题:7-2 字符串训练-字符排序
主要使用到了StringBuffer
在排序后,就实行以下代码输出(按ASCII码进行升序排序)。
StringBuffer sb = new StringBuffer();
for(int k =0;k<input.length();k++) {
sb.append(depart[k]);
}
System.out.println(sb.toString());
难度:易
第三题:7-3 正则表达式训练-验证码校验
题目要求如下:
接受给定的字符串,判断该字符串是否属于验证码。验证码是由四位数字或者字母(包含大小写)组成的字符串。
分析:
这个和第一题不同,这个匹配是可以是字母的,但是字母又可以是大写的,或者小写的,并且验证码为四位,在这四位验证码里面,每一个字符都可以是数字或者大写字母、小写字母,所以我写正则表达式的时候,匹配每一个字符的时候都是一样的规则,有四位验证码就重复四次就可以了,实现的demo如下
String match = "([0-9]|[a-z]|[A-Z]){4}";
难度:极易
第四题:7-4 正则表达式训练-学号校验
对软件学院2020级同学学号进行校验,学号共八位,规则如下:
- 1、2位:入学年份后两位,例如20年
- 3、4位:学院代码,软件学院代码为20
- 5位:方向代码,例如1为软件工程,7为物联网
- 6位:班级序号
- 7、8位:学号(序号)
这题也比较简单,首先可以确定软件学院的学号前四位都是2020开头,所以就用^(2020)规定匹配的字符串是以2020开头的数字,类似的,按照规则继续书写匹配度高的表达式。
如下所示:
String match = "^(2020)((1[1-7]|61)|7[1,2,3]|81|82)[0-4][0-9]¥";
最后也是通过匹配情况进行判断
boolean b =Pattern.matches(match,qq);
if(b) {
System.out.println("正确");
}
else
{
System.out.println("错误");
}
难度:极易(主要是这里的正则表达式书写起来很简单,而且匹配的东西很单一,就很简单,不像水文数据校验那一题,正则表达式书写就很繁琐,而且还用了很多次)
第五题:7-5 图形继承与多态
从键盘首先输入三个整型值(例如a b c),分别代表想要创建的Circle、Rectangle及Triangle对象的数量,然后根据图形数量继续输入各对象的属性值(均为实型数),数与数之间可以用一个或多个空格或回车分隔。
输出格式:
题目要求:
- 如果图形数量非法(小于0)或图形属性值非法(数值小于0以及三角形三边关系),则输出
Wrong Format。 - 如果输入合法,则正常输出,输出内容如下(输出格式见输入输出示例):
- 各个图形的面积;
- 所有图形的面积总和;
- 排序后的各个图形面积;
- 再次所有图形的面积总和。
就是要理清类与类之间的关系
主要是创建Circle、Rectangle及Triangle类,继承自Shape的父类,
Circle类里面有私有属性:半径。并且要计算出圆的面积,所以就需要一个返回已知半径圆的面积的方法,
public double getArea() {
return Math.pow(radius, 2) * Math.PI;
}
接下就是Rectangle类了,这个类里面有两个私有属性 : 长length和宽width,用来计算矩形的面积,
所以也需要一个方法用来计算矩形的面积:
public double getArea() {
return width * width;
}
再就是三角形类了:
里面有三个私有属:三条边side1、side2、side3,因为三角形三边需要一定的合法关系,所以必须得判定输入的吧三角形三条边是否合法,我解释一下我的思路:di
就是先用数组将三条边储存在里面,然后从小到大排序,首先判定最小的边是否大于零,也就是数组里面第一个元素,这样就能保证三条边都大于零,然后用最大的边减去最小的边,要求大于第三条边,还有一个规则就是最小的两条边相加要大于第三条边,以上条件都符合才能将三角形判定为合法三角形。
public boolean isTriangle() {
double[] sides = new double[3];
sides[0] = side1;
sides[1] = side2;
sides[2] = side3;
Arrays.sort(sides);
if (sides[0]<0) {
return false;
}
else if(sides[0]+sides[1]<sides[2]) {
return false;
}
else if(sides[0]+sides[1]==sides[2]) {
return false;
}
else
return true;
}
}
然后就是main方法的设计了。
main方法里面要有Circle、Rectangle及Triangle对象,然后注意传参的路径就可以了。
难度:难
第六题:7-6 实现图形接口及多态性
多态性的好处是代码可以与多个类一起工作,并且不需要知道正在使用哪个类,因为它们都以相同的方式使用。主要用于使应用程序模块化。可以创建根据当前需求选择的可互换对象,而不是使用创建不同操作的条件语句。而且多态性的原理是使您的组件保持独立,并且效果很好。
(5)总结:对本阶段三次题目集的综合性总结,学到了什么,哪些地方需要进一步学习及研究,对教师、课程、作业、实验、课上及课下组织方式等方面的改进建议及意见。
本次题目集让我加深了对正则表达式的理解,有些程序在自己的努力下自己写出来是一件很值得骄傲的事情,前提是这个题目不是难到没有思路,就是有难度,但是通过自己努力分析和查阅资料,能顺利地解决这个问题,在这个过程中提高了就自己地思维能力,也锻炼了自己地编程能力,所以,希望PTA上的题目难度适中,太难的题目真的太难受了,还有一个个人的建议,就是有时候做很难的题目,直到到了题目的提交后截止时间,还是有几个测试点没过,就截止提交后还想再思考一下这题的改进方法都没有地方可以提交了,我希望能另外开一个永久的题目集,让我们在截止提交后还能写这道题,这之后写的不算入平时分,就只是单纯地让我们琢磨,思考完善还没过的测试点。
最后再一次感谢老师的教导,感谢老师传授的知识,和在学习上对我的督促,能让我在这方面有卓越的提升!感谢老师。

浙公网安备 33010602011771号