对PTA(1~3)的作业总结(头裂)
前言:
学了一学JAVA(有点难),对于这三次作业的难度,我表示人麻了。关于作业(PTA)的一些总结,就一些题目的解题思路以及在解题过程中的收获,简单说一说。
这三次的题目集我感觉是一步步的牵引我们,从开始的具有浓厚的面向过程到面向对象的改变,关于知识点的考察(个人感觉)还是比较基础,难度不算太大,没怎么考验算法和思路,只是考验了代码的细节和一些边边角角,题量也中等偏上,但是随着难度的上升而减少。
题目分析及设计
PTA题目集1~(7-8 判断三角形类型)
对于这道题目,我的思路还是比较偏向于面对过程的编写,编程风格还是停留在C语言的层面上,没有面向对象的想法,
简单说一说个人思路
首先输入题目的限制条件(边的长度1~200),不合法直接输出Wrong Fromat。
然后再从输入的三条边中选出最长的那个边
无论如何最长的边是max,随后判断三角形的三边长度关系,不能构成三角形直接输出Not a triangle。
对于能构成三角形的三条边则进入。
判断三边相等 直接输出 Equilateral triangle。
有两边相等但不等于第三边时,判断是否是直角三角形,是则输出 Isosceles right-angled triangle,否则输出 Isosceles triangle。
对于任意的两条边不相等的时候,判断是否为直角三角形,是则输出 Right-angled triangle,否则输出 General,triangle。
到此如何判断三角形就解决了。
踩坑心得:
开始的时候我从判断勾股定理的想法入手,想着第三边的平方如果大于其他两边的平方和那他就是钝角三角形,小于的话就是锐角三角形,然后从钝角直角锐角中判断三边是否相等的关系以此来判断。
可是写着写着发现题目并没有要求你去判断是否是钝角和锐角三角形,只要求判断等腰,等边,直角和一般三角形,所以开始时候思路错误而且写的很混乱,几乎判断锐角和钝角完成后还要重复编写三边长度关系的代码,而且判断的过程很繁杂不能从多个IF中跳出来,不仅代码编写重复度高,代码编写的风格很糟糕,一眼看上去就头昏眼花。
PTA题目集2~(7-4 求下一天)
这道题目,我觉得讲究了JAVA中类的编写以及类中的方法使用,个人感觉有点类似于C语言中的函数编写,对于这一道求下一天的题目。思路就要想一想,不能直接就去做,
首先根据题目的要求设置一下数据的合法范围
(year >= 1820 && year <= 2020 && month >= 1 && month <= 12 && day >= 1 && day <= 31)
不满足的话直接就输出Wrong Format。
求一天,就要根据是哪个月,又是哪一年,我们先要判断是在那一年中,然后是那一年的月份中。
对于年份就分为了闰年和平年,闰年的二月份比平年的二月多了一天,如此一来,我们输入年时就要判断一下是否是闰年。
是闰年就返回true,不是会返回false。
如此一来,我就解决了如何判断闰平年。
随后判断输入的一天是否合法,如何判断呢,我先输入2019 2 30,可是在二月份里边没有30号,那它就是非法数据,不同的月份的天数不一样,二月份的天数受到闰平年的控制。
我就想了一下,我用两个数组,一个代表闰年和平年,数组装入月份的天数,第一个位置装入一月的天数,第二个位置装入二月的天数,以此类推,然后先判断是闰平年,再使用他们相应的数组就行。
这样就解决了输入的天数合不合法的问题。
到此判断天数合不合法,年份是否是闰年,都已解决。
还剩下如何求出它的下一天。
我的想法是,先解决普通的问题,
比如,2020 3 3 的下一天就是 2020 3 4。只要它的天数加1的值小于它这个月份的总天数,我就直接让它加个1。
当它要跨月的时候,2020 3 31 下一天是 2020 4 1 我们就将它的月份加1,然后天数等于1就行。
当它要跨年的时候,2020 12 31 下一天就是 2021 1 1,这个时候就将它的年份加1,月份和天数都等于1。
如此一来,问题就解决了。
踩坑思路:
这一道题看起来很复杂其实没太复杂,我们只要有一个大概的想法和思路就行,我们要先想出它的大概模型,然后再去思考一些细节问题,这样下去一个题目差不多就可以解决了,只要开始的时候不要想太多,一步一步慢慢思考就行,别太贪心想着一口气把问题解决。废话了一大堆,我来说说我一开始是怎么想的。
从开始拿到问题(求下一天),我就考虑了跨月份怎么办,不同的年怎么办,思考了不同的月份我该怎么处理。我先是思考了闰平年的判断,每次输入数据就去判断,每次日期改变就去依靠年份和改变前的月份去写(跨越月份就只用加1,如果加1后大于12就直接置为1,天数也就是根据是否大于该月份的天数,大于则置为1,否则就加1),只要注意细节这题目还是没有很大的难度。
PTA题目集2~(7-5 求前N天)
看见这一个题目就知道和上一道求下一天的题目有异曲同工之妙,我判断闰平年的方法可以接着用,判断输入的年月日数据是否合法也可以接着使用,但是我们要注意求前N天,不是求下N天,举个例子
2020 8 20 的前4天是 2020 8 16。 2020 8 16 的前-4天是 2020 8 20
2020 3 4 的前6天是 2020 2 27。 2020 2 27 的前-6天是 2020 3 4.
所以我们要注意跨越的月份如果是2月就要判断是否是闰年。
同理跨越年份的时候我们也要注意,比如
2020 1 4 的前4天是 2019 12 31。 2019 12 31 的前-4天是 2020 14。
这些情况我们也应该考虑进去。
所以我是这样写的。
开始的时候我就判断输入的数据是否合法
(year >= 1820 && year <= 2020 && month >= 1 && month <= 12 && day >= 1 && day <= 31&&n>=-10&&n<=10) 不合法就直接输出 Wrong Format.
然后开始判断日期与月份是否合法(顺便也要判断年份是否为闰平年)
随后开始对要求的N天开始取反,因为有一个‘前’字所以取反,开始的时候如果天数与N的和小于0说明就应该月份-1,并且天数等于上个月份的天数加上N与这个月的天数之和(如果是1月的话还应该年份-1),
此处的代码仅仅展示闰年的判断,如是平年的话直接else取另外一个数组即可。
至此的话。问题解决了。
踩坑心得:
在上一道题目的基础上,这道题的思路就和上一道差不太多了,在最开始的时候我在想求前N天,万一N=999,那我还得去计算这999天中跨了几个闰年几个平年,再根据年份去求月数,这不太麻烦了,结果仔细看一看才发现只用求-10~10范围内的值就行了(是我呆(sb)了)。这样一来题目就变得简单许多了,细节方面的话,其实只要考虑跨年(闰平年),跨月(1到2.2到3,3到2)就行。这道题和上面差不多我就不再赘述了。
PTA题目集~3(7-2 定义日期类)
这道题是我感觉比前面几道题目更加经典的题目,它让我感觉到了JAVA与C语言之间的不同编写方式以及风格,JAVA更加适用于多个情况。我也从这道题目里面学到了很多JAVA与C语言不同的东西。一个类的编写,一个类的属性,类的方法,如何创建一个私有的属性,如何调用和修改一个对象的私有属性,还有static这种静态的设置。废话不多说
关于这个DATE的类,如图的创建。
我想了想,这个和‘求下一天’那道题差不多,只不过这道题使用GET和SET去取得和设置数值几乎不影响我们去判断去改变任何东西,说明一下不使用GET和SET我们是无法在这个类的外面使用这个类里边的东西(个人看法),
这是我写的GET,SET方法。
随后,我们再调用GET和SET完成输出。
踩坑心得:
对于这道新的题目,我个人觉得,其实就是要讲究一下类的创建和类的私有属性写法,是一个极其基础的编写方法。解题思路也说完没有什么可以再说明的。
PTA题目集~3(7-3 一元多项式求导)
这道题目应该是这此作业里边难度最大,而且细节讲究太多了(测试点搞得我头发拉拉的掉),在这个题目里,我们要先知道求导,指数先和系数相乘然后自身减去一个1,随后讲究一下指数的正负和指数是否为1,当他为0时候直接输出他的系数。以及输出的时候‘+’和‘-’的讲究,主要是‘-’号的问题。
废话我就不再多说
直接上代码
此处对系数不为1,并且存在*的情况进行处理(个人感觉最麻烦的情况是在打印的部分)
对于‘+’的出现我们要考虑到指数的符号,比如指数为负数但是系数是负数此时我们就将系数的符号改为正数
这个有点烦人,但是解决完成后题目难度就降低了。
踩坑心得:
这道题目很麻烦,要讲究字符和整形之间的转化,以及那个项的指数的+-号还有那个系数的正负和为0时候的判断,常数的时候又该怎么办都是让人头痛的地方。还是要注重细节。
改进建议及总结:
通过自己查阅资料和自己平时的练习都可以发现自己的解题思路不是很清晰,对于不同的题目没有很快的做出一个反应,没有一下子就有个大致的思路,还是要四处碰壁才能找到正确的思路。
在写一个题目的时候,还是很“贪心”想要一下子就把程序写的很完美,想一下子就可以把题目解决,往往这样做只会导致做题的速度变慢以及思路混乱导致题目做不出来。
感觉还是自己锻炼的题目不够多,一些基础的只知识不太牢固导致,以后会更正自己的错误,在错误和实践中不断前行。
通过这次作业,我学到了JAVA的基本创建思想以及在类的方法和类的属性的设定以及他的使用。感觉自己的进步空间还很大。
(2021-10-15)
//作业源码
7-8 判断三角形类型:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double a;
double b;
double c;
double max;
a = input.nextDouble();
b = input.nextDouble();
c = input.nextDouble();
if (a >= 1 && a <= 200 && b >= 1 && b <= 200 && c >= 1 && c <= 200) {
if (a + b > c && a > c - b && b + c > a && b > a - c && a + c > b && c > b - a) {
if (a > b) {
max = a;
a = b;
} else
max = b;
if (c > max) {
b = max;
max = c;
} else
b = c;
if (max == a && max == b) {
System.out.print("Equilateral triangle");
}
if (a == b&&a!=max||a==max&&b!=max||b==max&&a!=max) {
if(a*a+b*b==max*max&&a==b)
System.out.print("Isosceles right-angled triangle");
else
System.out.print("Isosceles triangle");
}
if(a!=b&&b!=max&&max!=a){
if(max * max == a * a + b * b)
System.out.print("Right-angled triangle");
else
System.out.print("General triangle");
}
}
else
System.out.print("Not a triangle");
}
else
System.out.print("Wrong Format");
}
}
7-4 求下一天:
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();
if (year >= 1820 && year <= 2020 && month >= 1 && month <= 12 && day >= 1 && day <= 31) {
if (checkInputValidity(year, month, day)) {
nextDate(year,month,day);
} else
System.out.print("Wrong Format");
} else
System.out.print("Wrong Format");
}
public static boolean isLeapYear(int year) {
boolean isLeapYear = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
return isLeapYear;
}
public static boolean checkInputValidity(int year, int month, int day) {
boolean i;
int[] rmonth = new int[]{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int[] pmonth = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (isLeapYear(year)) {
i = (day <= rmonth[month - 1]);
return i;
} else
i = (day <= pmonth[month - 1]);
return i;
}
public static void nextDate(int year, int month, int day) {
int[] rmonth = new int[]{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int[] pmonth = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int days;
if (isLeapYear(year)) {
if(day==rmonth[month-1]){
if(month==12) {
year += 1;
month=1;
days=1;
}
else{
month+=1;
days=1;
}
}
else
days=day+1;
System.out.println("Next date is:"+year+"-"+month+"-"+days);
}
else{
if(day==pmonth[month-1]){
if(month==12) {
year += 1;
month=1;
days=1;
}
else{
month+=1;
days=1;
}
}
else
days=day+1;
System.out.println("Next date is:"+year+"-"+month+"-"+days);
}
}
}
7-5 求前N天:
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();
int n=input.nextInt();
if (year >= 1820 && year <= 2020 && month >= 1 && month <= 12 && day >= 1 && day <= 31&&n>=-10&&n<=10) {
if (checkInputValidity(year, month, day)) {
nextDate(year,month,day,n);
} else
System.out.print("Wrong Format");
} else
System.out.print("Wrong Format");
}
public static boolean isLeapYear(int year) {
boolean isLeapYear = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
return isLeapYear;
}
public static boolean checkInputValidity(int year, int month, int day) {
boolean i;
int[] rmonth = new int[]{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int[] pmonth = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (isLeapYear(year)) {
i = (day <= rmonth[month - 1]);
return i;
} else
i = (day <= pmonth[month - 1]);
return i;
}
public static void nextDate(int year, int month, int day,int n) {
int[] rmonth = new int[]{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int[] pmonth = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int days=0;
int m=-n;
if (isLeapYear(year)) {
if(day+m<=0){
if(month==1) {
year-= 1;
month=12;
days=31+m+day;
}
else{
month-=1;
days=rmonth[month-1]+day+m;
}
}
else if(day+m>rmonth[month-1]){
if(month==12){
year+=1;
month=1;
days=day+m-31;
}
else{
days=day+m-rmonth[month-1];
month+=1;
}
}
else
days=day+m;
System.out.printf("%d days ago is:%d-%d-%d\n",n,year,month,days);
}
else{
if(day+m<=0){
if(month==1) {
year-= 1;
month=12;
days=31+m+day;
}
else{
month-=1;
days=pmonth[month-1]+day+m;
}
}
else if(day+m>pmonth[month-1]){
if(month==12){
year+=1;
month=1;
days=day+m-31;
}
else{
days=day+m-pmonth[month-1];
month+=1;
}
}
else
days=day+m;
System.out.printf("%d days ago is:%d-%d-%d\n",n,year,month,days);
}
}
}
7-2 定义日期类:
import java.util.Date;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
Date da=new Date(input.nextInt(), input.nextInt(), input.nextInt());
if (da.getYear() >= 1900 && da.getYear() <= 2000 && da.getMonth() >= 1 && da.getMonth() <= 12 && da.getDay() >= 1 && da.getDay() <= 31) {
if (da.checkInputValidity()) {
da.nextDate();
} else
System.out.print("Date Format is Wrong");
} else
System.out.print("Date Format is Wrong");
}
public static class Date{
private static int year;
private static int month;
private static int day;
int[] rmonth = new int[]{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int[] pmonth = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
public Date(){}
public Date(int year,int month,int day){
this.day=day;
this.month=month;
this.year=year;
}
public int getMonth(){
return month;
}
public void setMonth(int month) {
this.month = month;
}
public void setDay(int day) {
this.day = day;
}
public int getDay() {
return day;
}
public void setYear(int year) {
this.year = year;
}
public int getYear() {
return year;
}
public static boolean isLeapYear(int year){
boolean isLeapYear = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
return isLeapYear;
}
public static boolean checkInputValidity() {
boolean i;
int[] rmonth = new int[]{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int[] pmonth = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (isLeapYear(year)) {
i = (day <= rmonth[month - 1]);
return i;
} else
i = (day <= pmonth[month - 1]);
return i;
}
public static void nextDate() {
int[] rmonth = new int[]{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int[] pmonth = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int days;
if (isLeapYear(year)) {
if(day==rmonth[month-1]){
if(month==12) {
year += 1;
month=1;
days=1;
}
else{
month+=1;
days=1;
}
}
else
days=day+1;
System.out.println("Next day is:"+year+"-"+month+"-"+days);
}
else{
if(day==pmonth[month-1]){
if(month==12) {
year += 1;
month=1;
days=1;
}
else{
month+=1;
days=1;
}
}
else
days=day+1;
System.out.println("Next day is:"+year+"-"+month+"-"+days);
}
}
}
}
7-3 一元多项式求导:
import java.math.BigInteger; import java.util.ArrayList; import java.util.LinkedList; import java.util.Scanner; /* * 此类用于对多项式表达式求导 * by@kaix2021/03/23 */ //Derivation 求导 public class Main { public static void main(String[] args){ Scanner in=new Scanner(System.in); String temp=in.nextLine(); DvForString dv=new DvForString(); dv.setPolynthic(temp);//预处理输入的字符串 dv.print(); //根据合法性作出不同输出 // System.out.println(); // dv.printEveryElement(); } } class DvForString{ private static LinkedList<String> item;//存储各项,此题并不需要 private static String sign,number,regex,regex1,regex2,regex3,concat,concatend,specialnum,end;//各项正则 //静态区,字符串 static { //静态区只在类被加载时被执行一次 item=new LinkedList<>(); sign="(?:[+|-])"; number="(?:([1-9](\\s*\\d*\\s*)*))"; //全是常数项时的特判 specialnum="((?:(\\s*([+|-]?[1-9]+\\s*\\d*)\\s*))*)"; //带x项,允许系数中间内有空格 //有不为0的系数和指数 regex="(?:(([1-9](\\s*\\d*\\s*)*)\\s*\\*\\s*x\\s*\\^\\s*[+|-]?\\s*([1-9](\\s*\\d*\\s*)*)))"; //x只有指数 regex1="(?:(x\\s*\\^\\s*[+|-]?\\s*([1-9](\\s*\\d*\\s*)*)))"; //x只有系数 regex2="(?:(([1-9](\\s*\\d*\\s*)*)\\s*\\*\\s*x))"; //x前面系数,指数都没有 regex3="(?:x)"; concat="("+regex+"|"+regex1+"|"+regex2+"|"+regex3+")"; //数字和带x项或在一起构成多项式中的一项 concatend="("+concat+"|"+number+")"; //多项式表达式 ,首项可以无+,-, 后续项必须有 end="(?:("+"\\s*"+sign+"?\\s*"+concatend+"(?:\\s*"+sign+"\\s*"+concatend+"\\s*)*"+"))"; } //Polynthic 多项式 private String Polynthic=null; public LinkedList<String> getItem() { return item; } //无参构造 public DvForString(){} //有参构造,可以直接通过字符串数组名赋值另一个相同大小和类型的数组 public DvForString(String polynthic) { this.Polynthic = polynthic; } //对私有变量获取和,赋值的方法 public String getPolynthic() { return Polynthic; } public void setPolynthic(String polynthic) { this.Polynthic = polynthic; } //合法性检验 private boolean isLegal() { boolean flag=true; String s=Polynthic; //全常数检验 if(s.matches(specialnum)) return true; //复杂多项式检验 if(!s.matches(end)) flag=false; return flag; } //打印合法输入中每一项 public void printEveryElement() { System.out.println(); if(isLegal()) { for(String e: item) System.out.println(e);} else System.out.println("Wrong Format"); } //打印 public void print() { if(isLegal()) printLegal();//合法结果打印 else printNotLegal();//不合法结果打印 } //打印不合法输出 private void printNotLegal() { System.out.println("Wrong Format"); } //打印合法输出 private void printLegal() { //拷贝一份给字符串s String s=Polynthic; s=s.replace(" ",""); char[] t=s.toCharArray(); for(int i=0;i<s.length()-1;i++) if(t[i]=='^'&&t[i+1]=='-') t[i+1]='#'; //直接通过tostring转换字符数组会出错,所以一个个字符拼接 String s1=""; for(int i=0;i<t.length;i++) s1=s1+t[i]; //再来整体替换- s1=s1.replace("^+","^"); s1=s1.replace("-","+-"); //如果+出现在第一个位置会报异常,要用\\+ String [] id=s1.split("\\+"); //加号输出标记 int flag=0; //无项时输出标记,标记若最终为0,最后输出0 int lazy=0; //所有常数直接打印不需要特意放+,带x项,对于大于0项,前面有其他项要打印出来 for(String e :id) { //切开后对每个元素进行分析处理,#要替换成- e=e.replace("#","-"); if(e!=null) item.addLast(e); int start=e.indexOf("x"); int mid=e.indexOf("*"); int end=e.indexOf("^"); //x,^都有 if(start!=-1&&end!=-1) { //系数不为1,存在* if(mid!=-1) { BigInteger pro=new BigInteger(e.substring(0,mid)); BigInteger pos=new BigInteger(e.substring(end+1,e.length())); BigInteger xishu=pro.multiply(pos);//乘法 BigInteger zhishu=pos.subtract(new BigInteger(1+""));//减法 if(zhishu.equals(new BigInteger(0+""))) System.out.print(xishu); else { if(xishu.equals(new BigInteger(1+""))) System.out.print("x^"+zhishu); else if(xishu.equals(new BigInteger(-1+"")))System.out.print("-x^"+zhishu); else { if( xishu.compareTo(new BigInteger(0+""))>0) if(flag==1) System.out.print("+"); System.out.print(xishu+"*x^"+zhishu); } } lazy=1; if(flag==0) flag=1; } //没有*,系数为负 else { if(e.charAt(0)=='-') { BigInteger pos=new BigInteger(e.substring(end+1,e.length())); BigInteger xishu=pos.multiply(new BigInteger(-1+""));//乘法 BigInteger zhishu=pos.subtract(new BigInteger(1+""));//减法 if(zhishu.equals(new BigInteger(0+""))) System.out.print(xishu); else { if(xishu.equals(new BigInteger(1+""))) System.out.print("x^"+zhishu); else if(xishu.equals(new BigInteger(-1+"")))System.out.print("-x^"+zhishu); else { if( xishu.compareTo(new BigInteger(0+""))>0) if(flag==1) System.out.print("+"); System.out.print(xishu+"*x^"+zhishu); } } } //没*,系数不为负 else { BigInteger pos=new BigInteger(e.substring(end+1,e.length())); BigInteger xishu=pos.multiply(new BigInteger(1+""));//乘法 BigInteger zhishu=pos.subtract(new BigInteger(1+""));//减法 if(zhishu.equals(new BigInteger(0+""))) System.out.print(xishu); else { if(xishu.equals(new BigInteger(1+""))) System.out.print("x^"+zhishu); else if(xishu.equals(new BigInteger(-1+"")))System.out.print("-x^"+zhishu); else { if( xishu.compareTo(new BigInteger(0+""))>0) if(flag==1) System.out.print("+"); System.out.print(xishu+"*x^"+zhishu); } } } lazy=1; if(flag==0) flag=1; } }//^,x都存在的分界线 //有x,没有指数 else if(start!=-1) { //有* if(mid!=-1) { BigInteger num=new BigInteger(e.substring(0, mid)); // if(num.compareTo(new BigInteger(0+""))>0) if(flag==1) System.out.print("+"); System.out.print(num); } //没有* else { BigInteger num=null; if(e.charAt(0)=='x') num=new BigInteger("1"); else if(e.charAt(0)=='-') num=new BigInteger("-1"); else num=new BigInteger(e.substring(0, start)); // if(num.compareTo(new BigInteger(0+""))>0) if(flag==1) System.out.print("+"); System.out.print(num); } lazy=1; if(flag==0) flag=1; } //常数 else System.out.print(""); }//大for结尾 if(lazy==0) System.out.println(0); } }