pta题目集1~3的总结性Blog

发布时间 2023-03-26 21:49:36作者: weiranwei

前言:

第一次题目集:主要针对java基础的语法,使用for循环,while循环,还有if语句在java中的使用,还有接收输入数据的scanner方法,获取输入的整形数据,字符数据,还有字符串数据,并且有着String对象的简单用法的涉及,如charAt(index)方法来查找创立string对象来返回字符串中指定位置的字符,length()方法来获取string对象中的字符数,indexOf(ch)方法来查找字符串中的相应的字符位置,Arrays类中sort()方法来排序数组等。第一次题目集的题量较大,但是难度偏低,给我一个适应java的过渡,构建初步对java中语法的使用。

第二次题目集:涉及了switch语句的用法,在题目一集的基础上加大难度,也涉及了if()和String对象的用法,还增加了输入强制转换数据的用法,对创建其他方法的使用和调用,更加深入于逻辑的层次,如最后两题判断三角形的类型对各类三角形的分类和如何进行判断,求下一天的逻辑方法,判断是否是闰年,判断原本日期之上,是否要进入下一个月,又是否要进入下一年,更锻炼逻辑思维。题量较第一次小,但难度偏大。

第三次题目集:包涵了要如何创建一个新的类,新类中存的数据的private型和public型,以及所创类中所要包涵的各类基础set和get方法,有参构造和无参构造,如何创建对象类。题目量少,难度大,偏向于锻炼逻辑思维。

设计与分析:

题目集三7-3

import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner input=new Scanner(System.in);
int year=input.nextInt();
int month=input.nextInt();
int day=input.nextInt();
Date date=new Date(year,month,day);
date.getNextDate();
}
}
class Date {
private int year;
private int month;
private int day;

public Date() {
}
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}

public boolean isLeapYear(int year){
if(year%400==0)
return true;
else if(year%4==0&&year%100!=0)
return true;
else return false;
}
public boolean checkInputValidity(){
if(year<1900||year>2000||month<1||month>12||day<1||day>31)
return false;
else if(isLeapYear(year)==false&&month==2&&day>28)
return false;
else return true;
}

public void getNextDate(){
if(checkInputValidity()==false)
System.out.printf("Date Format is Wrong");
else{
int[] list={31,28,31,30,31,30,31,31,30,31,30,31};
if(isLeapYear(this.year)==true)
list[1]=29;
day++;
if (list[month-1]<day){
day=1;
month++;
if(month>12){
month=1;
year++;
}
}
System.out.printf("Next day is:%d-%d-%d\n",year,month,day);
}
}
}

Date类里面有year,month,day等数据,isLeapYear()方法检测输入的年份是否为闰年,checkInputValidity()检查输入的信息是否合法,getNextDate()方法算出Date对象中下一天的数据并把数据打印,
getNextDate()方法中先调用checkInputValidity()方法判断输入的日期是否合法,不合法输入相应的提示,合法的话在进行下一天日期的计算,先创建一个数据储存十二个月的天数,再用isLeapYear()方法判
断是不是闰年,是闰年将数据储存的第二个月的信息赋为29,再用if语语句进行下一天的计算看要不要换月和换年,最后输出。
SourceMonitor的生成报表内容

 

PowerDesigner生成内容

 

 根据生成的数据可知,这题的难度不高,所需要的类的方法较少,代码质量一般。

题目集三7-4

import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int year = 0;
int month = 0;
int day = 0;

int choice = input.nextInt();

if (choice == 1) { // test getNextNDays method
int m = 0;
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());

DateUtil date = new DateUtil(year, month, day);

if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
}

m = input.nextInt();

if (m < 0) {
System.out.println("Wrong Format");
System.exit(0);
}

System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " next " + m + " days is:");
System.out.println(date.getNextNDays(m).showDate());
} else if (choice == 2) { // test getPreviousNDays method
int n = 0;
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());

DateUtil date = new DateUtil(year, month, day);

if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
}

n = input.nextInt();

if (n < 0) {
System.out.println("Wrong Format");
System.exit(0);
}

System.out.print(
date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " previous " + n + " days is:");
System.out.println(date.getPreviousNDays(n).showDate());
} else if (choice == 3) { //test getDaysofDates method
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());

int anotherYear = Integer.parseInt(input.next());
int anotherMonth = Integer.parseInt(input.next());
int anotherDay = Integer.parseInt(input.next());

DateUtil fromDate = new DateUtil(year, month, day);
DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);

if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
System.out.println("The days between " + fromDate.showDate() +
" and " + toDate.showDate() + " are:"
+ fromDate.getDaysofDates(toDate));
} else {
System.out.println("Wrong Format");
System.exit(0);
}
}
else{
System.out.println("Wrong Format");
System.exit(0);
}
}
}

class DateUtil{
private int year;
private int month;
private int day;
public DateUtil() {
}

public DateUtil(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}

public int getYear() {
return year;
}

public void setYear(int year) {
this.year = year;
}

public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}

public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public boolean checkInputValidity(){
if(year<1820||year>2020||month<1||month>12||day>31||day<1)
return false;
else return true;
}
public boolean isLeapYear(int year){
if(year%400==0)
return true;
else if(year%4==0&&year%100!=0)
return true;
else return false;
}
public DateUtil getNextNDays(int n){
DateUtil newDate=new DateUtil();
for(;n>400;){
if (isLeapYear(this.year) == true)
n=n-366;
else n=n-365;
this.year++;
}
n=n+this.day;
for(;n>0;){
int[] mon={31,28,31,30,31,30,31,31,30,31,30,31};
if(isLeapYear(this.year)==true)
mon[1]=29;
if(n>mon[this.month-1]) {
n = n - mon[this.month -1];
this.month = this.month + 1;
if (this.month == 13) {
this.year = this.year + 1;
this.month = 1;
}
}
else{
newDate.day=n;
newDate.month=this.month;
newDate.year=this.year;
n=-1;
}
}
return newDate;
}
public DateUtil getPreviousNDays(int n){
DateUtil newDate=new DateUtil();
for(;n>400;){
if (isLeapYear(this.year) == true)
n=n-366;
else n=n-365;
this.year--;
}
for(;n>this.day;) {
int[] mon={31,28,31,30,31,30,31,31,30,31,30,31};
if (isLeapYear(this.year) == true)
mon[1] = 29;
n = n - this.day;
if (this.month == 1) {
this.year--;
this.month = 12;
} else this.month--;
this.day = mon[this.month - 1];
}
this.day=this.day-n;
newDate.day=this.day;
newDate.month=this.month;
newDate.year=this.year;
return newDate;
}
public boolean compareDates(DateUtil date) {
if(date.year>this.year)
return false;
else if(date.year==this.year&&date.month>this.month)
return false;
else if(date.year==this.year&&date.month==this.month&&date.day>this.day)
return false;
else return true;
}
public boolean equalTwoDates(DateUtil date) {
if(date.year==this.year&&date.month==this.month&&date.day==this.day)
return true;
else return false;
}
public int getDaysofDates(DateUtil date) {
int sum=0,i;
if(date.year<this.year) {
i=date.year;
date.year=this.year;
this.year=i;
i=date.month;
date.month=this.month;
this.month=i;
i=date.day;
date.day=this.day;
this.day=i;
}
else if(date.year==this.year&&date.month<this.month) {
i=date.year;
date.year=this.year;
this.year=i;
i=date.month;
date.month=this.month;
this.month=i;
i=date.day;
date.day=this.day;
this.day=i;
}
else if(date.year==this.year&&date.month==this.month&&date.day<this.day) {
i=date.year;
date.year=this.year;
this.year=i;
i=date.month;
date.month=this.month;
this.month=i;
i=date.day;
date.day=this.day;
this.day=i;
}
sum = -this.day;
this.day = 0;
if (this.year < date.year) {
for (;this.year < date.year;) {
int[] mon = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if(isLeapYear(this.year)==true)
mon[1] = 29;
for (; this.month <= 12; ) {
sum = sum + mon[this.month - 1];
month++;
}
month = 1;
this.year++;
}
}
int[] mon = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if(isLeapYear(this.year)==true)
mon[1] = 29;
for(;this.month<date.month;) {
sum=sum+mon[this.month-1];
month++;
}
sum=sum+date.day;
return sum;
}
public String showDate(){
String time=year+"-"+month+"-"+day;
return time;
}
}

DateUtil类中checkInputValidity()方法检测输入的日期是否合法;isLeapYear(int year)方法来检测输入的年份是否为闰年;getNextNDays(int n)方法来获取下n天的的日期;getPreviousNDays(int n)的
方法来获取前n天的日期;compareDates(DateUtil date)方法来比较对象中的日期和输入的日期的先后;equalTwoDates(DateUtil date)方法来比较输入的两个日期是否是同一天;getDaysofDates(DateUtil date)
方法来获取后n天的日期;showDate()方法将日期转化为字符串输出;

主方法先通过if()语句来筛选计算的日期是前n天还是后n天,还是两个日期的间隔,然后再创建对象,把对象接受相应的输入的信息,调用各类的方法进行相应的计算,最后再把计算得到的日期输出。
getDaysofDates(DateUtil date)方法中当时没有运用compareDates(DateUtil date)方法来判断日期的前后,导致运用了一连串的if()语句先来判断日期的前后,看看两个日期是否需要交换导致代码太过冗长。
 

SourceMonitor的生成报表内容

 

 PowerDesigner生成内容

 

 根据生成的数据分析可知,代码太过冗长,复杂度较高,以导致代码的质量低下,在以后的编程过程之中会多加注意,思索出更好的方法来编写代码,确保代码的质量。

 

 

踩坑心得:

 

 

问题1:

对于这题剔除重复的数据,一开始采用了两个for循环来用不断重复重头开始查找是否有重复的数据,但两个for循环在输入的数据过多的时候会出现运行超时,一直无法通过测试用例。

解决方法:

使用Arrays.sort()方法来对数组的数组进行排序,再用if语句判断是否数据中第i个数据和第i+1个数据是否相同,如此只需要一个for循环就可解决。

 

 

 

 问题二:输出的数据类型精度不准确。

解决方法:将要输出的数据强制转化为float类型再进行输出。

 

 

 

 问题三:出现逻辑错误,对求值的算式错误。

解决方法:结合题目的要求,重新修改了算式。

问题四:题目集三的第四题日期类的设计中计算下n天和前n天在n太大的时候,运行超时,原代码只用输入的天数一天天加上去,遍历次数过多,n有多大就需要加多少次,太过冗长。

解决方法:先判断出年份是否为闰年,如若是闰年,并且输入的天数大于366就减去366天,如若判断不是闰年,并且输入的天数大于365就减去365天,再接着判断剩下的天数是否大于当前月份的天数,如若大于就直接减去。

 

 

 

问题五:出现了了年份增长到13月的情况,年份不增加。

解决方法:加上对月份如果大于13就加一年的判断。

 

改进建议:

1.自己对于参数名的使用和各类变量名的命名有一些没有采用到lowerCamelCase风格,类名没有采用UpperCameCase风格,没有遵从驼峰行,有一些变量就直接用i,j等字符表示,使得代码无法研读,而且在书写代码的时候没有写注释的习惯,没有任何的解释,使得代码难以研读,书写代码的格式没有用老师给出的阿里的规范,行距和字母与标点符号之间的空格没有把控,每个for循环和其他的if()语句的缩进没有把控好。以后会加以改进,对类名还有各种变量的命名定采用规定风格,对变量命名做到见名思意,不怕命名太过于冗长,写代码的时候下意识地去下注释以养成习惯,标点符号,如等号,两边空格等阿里规范做好,使之成为习惯。

2.

 

 当时书写了一连串的if()语句来进行输入字符的判断,如此以来分支过多,代码的复杂程度高,而且书写起来冗长,可以使用Switch()语句与这一连串的if()语句替换,可以简化代码的长度,而且减少分支结构,显得简练。

3.

 

 当时这道重复数据的题目,我一开始是采用两个for循环来重复遍历但一直运行超时才用了Array.sort()函数先将其排序再来for循环检测第i个数和第i+1个数是否相同,现在可以再将得到的数组赋予到新的harshset定义的整型对象的数组中,因为如果有harshset中不会有重复的数据,当出现重复的数据时就会忽略不加,如此我们就可以比较新的harshset的整型数组和原来的数组长度是否相同,如果相同则是没有剔除任何的数,则是原数组中没有重复的数据,否则就有重复的数据,如此以来就不用再用for循环再次遍历数组再一个个进行判断。

4.

 

 这道是使用了双循环for来抽取输入的第一个字符串中的一个个字符与要剔除的字母的字符串中的一个个字符进行比较,如果都没有相同的就可以判断出这个字符是不用剔除的,就将这个字符输出,这样的代码运行起来过于慢,两个for循环遍历两个字符串所用的时间过久,浪费的内存过多,可以创建一个ArrayList字符串型的对象数组,接收第一个输入的字符串中的所有字符,再用contains()方法来判断是否有与要剔除字符串中的字符,如若有就用remove()方法将对应的字符从ArrayList的对象数组中移除,这样做就可以避免两个for循环的使用,不用一个个遍历,节省内存。

 

总结:

经过了对java的初步的系统学习,并通过这几次三次的pta题目集的训练,我逐渐了解了java和C语言之间的相同和不同,使用java编程会有着众多方法索引的帮助,编程起来会更加便利,并且java中没有了C语言中复杂的指针和链表的使用,转化为一种更为简单的方式,而java是面向对象的语言,其中更加注重私有性,学习了迪米特法则,尽可能做类与类之间的耦合性低,使得每个模块的联系降低,每个模块相对于独立。通过了这几次pta的练习我学习到了java的基本语法规则,String类的各种方法使用,如charAt(),检测字符串长度的length()方法,比较字符串是否相同的equals()方法,比较字符串的大小的compareTo()方法,还有查找字符的indexOf()方法,Arrays.sort方法来整理数组,使数组按序排列。如何去定义不同的类,以及去区分不同类之间的关系,还有不同类之中的方法创建问题和设计问题,如何将创建的方法以更好方法实现代码实现,还有java的特性之一的封装性,每个类相互独立,有一些数据是别的类不能访问的private型还有一些是别的类可以访问的public型,我觉得这于C语言有着很大的区别,C语言的所有数据都可以用的,没有区分私有型和公有型。还认识了java的diea编译器的大致使用方法,如何创建类等等,通过了这些题目集的训练,巩固了我对string类,还有for等循环语句在java中的使用,尤其是第三次题目集的日期类的题目使我对日期类计算的逻辑更为深刻,虽然在那道题上花费了很多的时间,通过不断地改进,不断运用各种的方法,查找其中出现的错误也让我收获了很多。不过对于各类之间的低耦合性并不能很好的把控,对于String类,还有其他的Arrays类,ArrayList类的各类方法还不能够熟记,有时候还会把不同类其中的方法混淆,想要在一个类里面使用其他类的方法,只能通过编译器给出的索引来查找,这大大降低了我书写代码的效率,之后我会对各类的方法加以熟记,还有对低耦合性加以研究,争取做到。我认为课程教学紧凑,课上只需要为我们指明需要学习的方向,其余的相应类的方法只需要我们课后再去学习即可,这可以大大增加课堂上的效率,以及我们的学习效率。