pta第一到第三次题目集

发布时间 2023-03-26 21:49:36作者: 熊建新

(1)前言

pta第一次作业的7-1,7-2,7-4主要熟悉运用了 if-else 的语句使用,以及运用System.out.printf进行格式化输出,7-3九九乘法表主要学会了运用for循环及多重循环的使用7-5到7-10,在运用循环和if-else语句的同时,学会了应用String类,对字符串进行输入和输出,同时对String类中的方法有了更多的了解。总体量感觉较大,题目较多。

pta第二次作业7-1到7-8主要是对第一次题目集的巩固,加深了对if-else的使用,其中7-5利用switch-case能替代if-else更好的解决问题,7-9为压轴题,对类与对象的概念有了初步的认识,该题难度较大。

pta第三次作业7-1到7-2难度较为简单,对类与对象的概念有了更深的一步见解,后7-3,7-4是第二次作业中求下一天的迭代,认为难度较大,一题的量抵10题!!!

(2)设计与分析(对题目源码分析,参考power。。有相应的解释和心得)

--训练题集01和训练题集02中的题目较为简单,未涉及到较多方法和类,主要是以熟悉if-else语句,嵌套for循环,String类内方法的调用,以及简单日期类的设计。训练题集01中7-1,7-2,7-4,以及训练题集02中7-4,7-5,7-8中主要训练了if-else和switch-case语句的使用,并结合了String类中几个方法的使用,以02中的7-4与7-5中部分代码为例子:

7-4:

7-4中 输入案例如下:两个整数:游戏种族、角色的选项,以空格分隔。例如:1 2。

种族选项设定为:1、人类 2、精灵 3、兽人 4、暗精灵
角色选项设定为:1、战士 2、法师 3、射手

发现选项设定都为整型常量 ,并且各个常量代表的选项不同,便立马想到switch语句中的两个规则:

case标签必须是常量表达式(constantExpression),如62或者’8’等。

case标签必须是唯一表达式;也就是说,不允许两个case具有相同的值。

所以先创建两个变量a,b,然后用一个if语句限制a,b的值限制为选项中要求的值,也就是1-4和1-3,紧接着使用switch-case语句,就能轻松解决,但最后测试代码的时候发现,一套流程下来,结果还是有误,当我输入了1 1的时候 测试用例中输出了4个种族和3个角色,说明没有进行单一选择,后面再看switch语句的用法,发现每个case语句结束后,都少了break;以至于进入到case 1后,后面的case语句都进入了,导致了问题的出现,所有修改代码的时候,每个语句后面都增加了break;最后测试便成功了。

7-5:

7-5中案例如下:

学校的学号由8位数字组成,前两位是入学年份(省略了20);第3、4位是学院编号,01代表材料学院,02代表机械学院,03代表外语学院,20代表软件学院;第5、6位是学院内部班级编号,最后两位是班级内部学号。如:18011103,入学年份是2018年,材料学院,11班,03号     8位数字组成的学号。输入案例:例如:18011103   注意:输入学号不是8位或者学院编号不是01、02、03、20其中之一,属于非法输入

开始的时候在纠结是否使用字符数组,但发现其中都是两两字符出现,所以采用了String类来对输入进行处理,由于每两位数的组成代表不一样的事物,想到调用String类中substring方法,这样可以有效的将特定下标的两个字符取出,最后使用equalsIgnoreCase进行提取出的字符串与题目给出的进行比较(不能讲字符串用“==”进行比较,java中字符串的比较是==比较引用,equal比较值,例如  案例一: String a="abc";String b="abc",那么a==b将返回true。因为在java中字符串的值是不可改变的,相同的字符串在内存中只会存一份,所以a和b指向的是同一个对象;

               案例二:String a=new String("abc"); String b=new String("abc");那么a==b将返回false,此时a和b指向不同的对象。)成功解决问题。

 

--训练题集03中4题都是类与对象及方法的设计与使用,前两题为基础题,7-3,7-4为日期类的迭代,难度系数较高,7-3与7-4案例如下:

7-3类的设计以及部分主函数源码:

 

 

 

 定义日期类,主要包含无条件构造对象和有条件构造对象,以及多个方法,。

其中判断闰年方法比较简单当该年能够被4整除并且不被100整除或者该年能直接整除四百,则为闰年,返回true的值,否则返回false值,所以一个if语句就可以解决该问题。

 

判断输入年份年月日是否正确的时候,则要调用isLeapYear方法,因为闰年时,2月份的日子为29天,所以需要调用该方法,接下来按照题目要求用if语句判断是否在正确范围内。

获取下一天的方法则需要,再次调用checkInputVlidity方法,实现了方法的迭代,接下来需要注意的是月份的最后一天和年份的最后一个月,多个if-else进行条件判断,最后求得下一天,最后通过测试。

 

 --训练题集中7-4日期类设计在当时写的时候,可谓是一波三折,算是最难最难的题目了,虽然不用写主函数,只要设计类和方法,但是是前两次作业日期类的迭代中的迭代!!!类与方法的设计主要如下:

 

 

public DateUtil getNextNDays(int n);//取得year-month-day的下n天日期

public DateUtil getPreviousNDays(int n);//取得year-month-day的前n天日期

public boolean compareDates(DateUtil date);//比较当前日期与date的大小(先后)

public boolean equalTwoDates(DateUtil date);//判断两个日期是否相等

public int getDaysofDates(DateUtil date);//求当前日期与date之间相差的天数

public String showDate();//以“year-month-day”格式返回日期值

其中有需要

应用程序共测试三个功能:

  1. 求下n天
  2. 求前n天
  3. 求两个日期相差的天数

求下n天的时候,当时想的是,利用一个for循环,然后将求下一天的方法导入进去,未超过n天,则继续循环求出下一天,于是再次迭代,将求下一天方法放入求下n天的方法中,最后求出了下n天的结果。求前n天情况类似,先写出求前一天的方法,再利用for循环 带入到求前n天的方法中去。

但测试结果如下:

 

 

 虽然都是对的,但是耗时实在是太高了,一单要求测试大一点的整数,要等待的时间实在太长,不符合设计程序的初衷,所以对求下n天的方法进行了改进:要么去除部分循环,要么使循环次数变小,我选择了后者;

 

 

 这样n在每轮循环中至少减去365,相较于上图,大大减少了循环的次数,提高了效率。

在求两个日期差的天数时,也是将判断日期大小以及日期是否正确的方法调入到其方法中。最困扰我的是算法,但也是想了一些时候想出来了:首先求出另两个日期的年份差,然后将差值*365天(由于其中可能包含闰年,则需要for循环以及if-else语句判断,将每年的天数相加),然后将日期大的月份每个月的天数相加,再减去日期小的月份的每个月的天数,最后求得日期差,具体代码和方法如下:

 

 (判断日期是否相等,相等则返回n,初值为0)   (判断年份是否有差异)

最后经过一系列循环,返回最后n的值,得到相差的天数

(3)采坑心得

--训练集中7-2中的第九行容易把“||”打成“&&”,造成测试数据出错(这个点在一开始其实很容易想到,但是下意识打成了“||”,属实不应该)

 

 --训练集2中7-4运用的switch-case语句中,开始容易把break给遗漏掉,导致输出的结果有多行,测试时发现问题(switch 要break ,switch 要break,switch 要break   重要的事说三遍!!!!!)

 

 --训练集02中的7-8的14行判断直角三角形两边平方和等于斜边平方,但在java浮点数中应该写为平方和与斜边平方差小于一个较小值,因为浮点数做算术会有误差,这题测试点一直没过就在这里:浮点数做算术有误差!!!!

 --训练题集03中7-4的日期类设置中,由于开始在求下一天的方法中判断2月是否为闰月时使用if未用else,导致在求下n天的时候,一但有一年判断为闰年,接下来的每年2月都会是29天,最后导致求下n天的时候一直会出现2-3天的误差。(注意if-else在循环语句中的使用,不能偷懒少了else!!!)

 

 

 

(4)改进建议(对编码给出见解)

1.首先我认为主要需要改进的地方,是在那些出现了较多判断条件的题目,特别是其中if-else和switch-case的选择。例如训练题集01中的7-1,7-2,7-4,以及题目集02中的7-4,7-5,7-8。大部分运用的是if-else语句,原因如下:

当分支较多时,当时用switch的效率是很高的。因为switch是随机访问的,就是确定了选择值之后直接跳转到那个特定的分支,但是if...else是遍历所以得可能值,知道找到符合条件的分支。如此看来,switch的效率确实比if-else要高的多。

switch...case只能处理case为常量的情况,对非常量的情况是无能为力的。例如 if (a > 1 && a < 100),是无法使用switch...case来处理的。所以,switch只能是在常量选择分支时比ifelse效率高,但是ifelse能应用于更多的场合,ifelse比较灵活。

例如题目集02中7-5的代码如下:  如果选择的分支大于或等于下列情况,我会选择用switch-case语句。

 

 2.我认为最需要改进的,是训练题集03中7-4的求下n天,当时提交的代码如下:

 

 

 

 在求下n天的方法中,使用了求下一天的方法,再加入for循环,看是非常合理且方便,实际上:

 

 耗时达到了8秒多!!!!!!!!!  这说明该循环结构循环较大(最大达到10000天!!!)自身的算法出现了问题,然后便换了一种思路  部分代码如下:

 

 这样下来便解决了最根本的问题 ,循环的次数减少了,运行时长大大减少,由8秒多变成了200毫秒。

(5)总结

 这前三次作业是老师布置的第一次作业,也是我入门java的第一次作业,题目总体来说难度中等,毕竟就算不能达到速成代码的境界,但较难的题目也能被自己软磨硬泡弄出来。自身的java语法得到了提高,对类和方法的设计也有了进一步的认知和理解,但自身java语法基础仍然比较薄弱,例如String的方法有些仍然不能灵活运用,以及对类与对象的理解仍然不足,下一步,首先继续保持java的系统不断点的线上学习,多上机实验,将知识转化到程序代码上。

对课程和老师的建议:希望在pta上布置一些中等难度的题目,尽量涉及到新学的内容,方便记忆,同时希望课堂上讲的知识能够运用到实例上展示出来。(目前确实很多东西感觉学了没有结合具体例子或操作,等于0)现在课程任务量挺大的,累点不要紧,要紧的是累点的话,要学会真本事。