PTA 题目集1-3总结

前言:

其实这三次作业我对java面向对象的思想不是很清楚,自己也是按照上学期数据结构的方法去写,然后发现自己的代码太复杂,并且不易看懂。

题目集1知识点:

Scanner 的用法,java的输入和输出、对一些条件的判断,简单可以说跟之前的数据结构解题思想差不多。

题目集2知识点:

函数的调用

.toCharArray()的用法

.length()的用法

数组的定义

System.exit(0)的运用

题目集3知识点:

让我们开始用类的设计来解决题目

substring()的用法

BigInteger的用法

PTA 7-8 判读三角形类型

踩坑心得:

其实这道题就只有一个坑,那就是double 型运算是会出现误差,就比如下面这个例子

import java.util.Scanner;
​
public class Main {
​
    public static void main(String[] args) {
    double a = 1.0;
    double c= 0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1;
    if(a == c) {
        System.out.println(true);
    }
    else
        System.out.println(false);
    System.out.print("a = " + a +"   c = "+ c);
}
    
}

 

我们如果自己去看会发现 a和c应该是相等的,但实际上呢?

false a = 1.0 c = 0.9999999999999999

 

计算机会告诉我们c=0.9999999999999而a=1,他们两并不会相等,所以我们该怎么办呢?

import java.util.Scanner;
​
public class Main {
​
    public static void main(String[] args) {
    double a = 1.0;
    double c= 0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1;
    if(a - c < 1e-6) {
        System.out.println(true);
    }
    else
        System.out.println(false);
    System.out.print("a = " + a +"   c = "+ c);
}
    
}

 

我们只需让a-c小于一个很小的数(1e-6就是0.000001)就可以解决该问题

true a = 1.0 c = 0.9999999999999999

 

源代码:

import java.util.Scanner;
​
public class Main {
​
    public static void main(String[] args) {
        // TODO Auto-generated method stub
      Scanner in = new Scanner (System.in);
      double a,b,c;
      a = in.nextDouble();
      b = in.nextDouble();
      c = in.nextDouble();
      if(a < 1 || a > 200 ||b <1 || b > 200 || c <1 || c > 200 ) {   //题目给出的范围
          System.out.print("Wrong Format");
      }
      else if((a + b) <= c || (a + c) <= b || (b + c) <= a) {   //判断是否是一个三角形
          System.out.print("Not a triangle");
      }
      else if (a == b && b == c) {     //判断是否是一个等边三角形
          System.out.print("Equilateral triangle");
      }
      else if(a == b || b == c || a == c) {
          if(Math.abs(a*a + b*b -c*c)< 1e-6 || Math.abs(a*a + c*c -b*b) <  1e-6 || Math.abs(b*b + c*c- a*a) < 1e-6) {   //判断是否是等腰直角三角形
              System.out.print("Isosceles right-angled triangle");
          }
          else {   //判断是否是等腰三角形
              System.out.print("Isosceles triangle");
          }
      }
      else if(Math.abs(a*a + b*b -c*c)< 1e-6 || Math.abs(a*a + c*c -b*b) <  1e-6 || Math.abs(b*b + c*c- a*a) < 1e-6) {//判断是否是直角三角形
          System.out.print("Right-angled triangle");
      }
      else {  //判断是否是普通三角形
          System.out.print("General triangle");
      }
          
    }
​
}

 


反思:

自己还是停留在面向过程,没有面向对象的思想,自己的代码写的if-else太多导致自己代码的圈复杂度太高。以下为SourceMonitor软件的分析可以看成自己写的分支太多,较为复杂。

 

PTA 7-4 求下一天

需要注意的细节:

(1)平年的2月是29天,闰年的2月是28天,在判断数据的合法性和求下一天要判断

判断数据合法性:

        
    else {    //当月数为2
                if(isLeapYear(year) == true) {  //该年为闰年时
                    if(day > 29 || day < 1) {   //输入非法
                        return false;
                    }
                    else {       //输入合法
                        return true;
                    }
                }
                else {          //该年为平年
                    if(day > 28 || day < 1) {   //输入非法
                        return false;
                    }
                    else {   //输入合法
                        return true;
                    }
                }
            }

 

求下一天时:

        else if(month == 2) {   //当月数为2
             if(isLeapYear(year) == true) { //该年为闰年,天数28天
                 if(day != 29) {
                     day++;
                 }
                 else {
                     month++;
                     day = 1;
                 }
             }
             else {    //该年为平年,天数29天
                 if(day != 28) {
                     day++;
                 }
                 else {
                     month++;
                     day = 1;
                 }
             }
         }

 

(2)一年里的最后一天,也就是12月31日,也需要分开来判断。

      else if(month == 12) {   //当月数为12
                 if(day != 31) { 
                     day++;
                 }
                 else {       //刚好为下一年的第一天
                     year ++; 
                     month = 1;
                     day = 1;
                 }
             }

 

源代码:

package pta;
​
import java.util.Scanner;
​
public class P4 {
​
    public static void main(String[] args) {
        // TODO Auto-generated method stub
          Scanner in = new Scanner (System.in);
            int year,month,day;
            year = in.nextInt();   
            month = in.nextInt();
            day = in.nextInt();    //输入年,月,日
            if(checkInputValidity(year,month,day) == false) {  //输入数据非法
                System.out.print("Wrong Format");
                System.exit(0);   //直接退出程序
            }
            nextDate(year,month,day);
    }
    public static void nextDate(int year,int month,int day) {  //输出下一天
         if(month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 ) {  //当月有31天
             if(day != 31) {  
                 day++;
             }
             else {
                 month++;
                 day = 1;
             }
         }
             else if(month == 4 || month == 6 || month == 9 || month == 11 ){   //当月有30天
                 if(day != 30 ) {
                     day++;
                 }
                 else {
                     month++;
                     day = 1;
                 }
             }
             else if(month == 12) {   //当月数为12
                 if(day != 31) { 
                     day++;
                 }
                 else {       //刚好为下一年的第一天
                     year ++; 
                     month = 1;
                     day = 1;
                 }
             }
             else if(month == 2) {   //当月数为2
                 if(isLeapYear(year) == true) { //该年为闰年,天数28天
                     if(day != 29) {
                         day++;
                     }
                     else {
                         month++;
                         day = 1;
                     }
                 }
                 else {    //该年为平年,天数29天
                     if(day != 28) {
                         day++;
                     }
                     else {
                         month++;
                         day = 1;
                     }
                 }
             }
         System.out.print("Next date is:" + year + "-" + month + "-" + day);  //输出下一天
    }
​

public static boolean checkInputValidity(int year,int month,int day) {   //判读输入日期是否合理,返回boolean类型
if(year < 1820 || year > 2020 || month < 1 || month > 12 ) {   //判读是否符合题目给出的年和月的范围
            return false;
            }

            if(month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {  //当输入的月有31天时
            if(day > 31 || day < 1) {   //当输入天数超过31或者小于1
            return false;
                }
            else {   //输入合法
            return true;
                }
            }
            else if(month == 4 || month == 6 || month == 9 || month == 11 ){ //当输入的月有30天时
            if(day > 30 || day < 1) {   //当输入的天数小于30天或者小于1
            return false;
                }
                else   //输入合法
                    return true;
            }
            else {    //当月数为2
            if(isLeapYear(year) == true) {  //该年为闰年时
            if(day > 29 || day < 1) {   //输入非法
            return false;
                }
            else {       //输入合法
            return true;
                }
                }
            else {          //该年为平年
            if(day > 28 || day < 1) {   //输入非法
            return false;
                }
            else {   //输入合法
            return true;
                }
                }
            }
    }
public static boolean isLeapYear(int year) {//判断year是否为闰年,返回boolean类型;

if(year%4 == 0 && year%100 != 0 || year%400 == 0 ) {  //判断为闰年
return true;
    }
else {   //判断为平年
return false;
    }
    }
​
}

 


 

反思:

写完之后自己就发现其实自己在写if-else很多重复的内容,导致自己的分支写太多,导致复杂性变高。后面发现可以写一个类把几个特殊情况写成几个函数,当需要判断是则调用函数即可。

 

 

PTA 7-2定义日期类

心得:

这道题的其实没什么坑,主要是让你开始用面向对象的思想来解决问题,差不多就像下面一样照着写:

class Data{
      int year;
       int month;
       int day;   
       int[] a = new int[] {0,31,28,31,30,31,31,30,31,30,31};
       public Data(int year, int month, int day) {
          this.year = year;
          this.month = month;
          this.day = day;
       }
       public Data() {
           
       }
       public int getyear() {
           return year;
       }
       public int getmonth() {
           return month;
       } 
       public int getday() {
          return day;
       }
       public void setyear(int year) {
           this.year=year;
       }
       public void setmonth(int month) {
           this.month=month;
       }
       public void setday(int day) {
           this.day=day;
       }

 

源代码:

package pta1;
​
import java.util.Scanner;
​
public class P2 {
​
    public static void main(String[] args) {
        // TODO Auto-generated method stub
       Scanner in = new Scanner(System.in);
       Data a = new Data();
       a.setyear(in.nextInt());
       a.setmonth(in.nextInt());
       a.setday(in.nextInt());
     if(  a.checkInputValidity(a.getyear(), a.getmonth(), a.getday()) == false) { 
          System.out.print("Date Format is Wrong");
          System.exit(0);
     }
     a.nextDate(a.getyear(), a.getmonth(), a.getday());
    }
    
​
}
class Data{
      int year;
       int month;
       int day;   
       int[] a = new int[] {0,31,28,31,30,31,31,30,31,30,31};
       public Data(int year, int month, int day) {
          this.year = year;
          this.month = month;
          this.day = day;
       }
       public Data() {
           
       }
       public int getyear() {
           return year;
       }
       public int getmonth() {
           return month;
       } 
       public int getday() {
          return day;
       }
       public void setyear(int year) {
           this.year=year;
       }
       public void setmonth(int month) {
           this.month=month;
       }
       public void setday(int day) {
           this.day=day;
       }
       public static void nextDate(int year,int month,int day) {  //求下一天
             if(month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 ) {  //当月有31天
                 if(day != 31) {
                     day++;
                 }
                 else {
                     month++;
                     day = 1;
                 }
             }
                 else if(month == 4 || month == 6 || month == 9 || month == 11 ){ //当月有30天
                     if(day != 30 ) {
                         day++;
                     }
                     else {
                         month++;
                         day = 1;
                     }
                 }  
                 else if(month == 12) {  //12月,判断是否跨年
                     if(day != 31) {
                         day++;
                     }
                     else {
                         year ++;
                         month = 1;
                         day = 1;
     }
     }
else if(month == 2) {   //当2月时
if(isLeapYear(year) == true) {  //该年闰年
if(day != 29) {
day++;
     }
else { 
month++;
day = 1;
     }
     }   //该年平年
else {
if(day != 28) {
day++;
     }
else {
month++;
day = 1;
     }
     }
     }
System.out.print("Next day is:" + year + "-" + month + "-" + day);
    }
public static boolean checkInputValidity(int year,int month,int day) {  //判断年月日是否输入合法
if(year < 1900 || year > 2000 || month < 1 || month > 12 ) {   //判断是否题目给出的范围
            return false;
            }
            if(month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
            if(day > 31 || day < 1) {   //输入非法
            return false;
                }
            else {  //输入合法
            return true;
                }
            }
            else if(month == 4 || month == 6 || month == 9 || month == 11 ){
            if(day > 30 || day < 1) {  //输入非法
            return false;
                }
            else    //输入合法
            return true;
            } 
            else {    //当月为2月
            if(isLeapYear(year) == true) {    //该年为闰年
            if(day > 29 || day < 1) {   //输入非法
            return false;
                }
            else {      //输入合法
            return true;
                }
                }
            else {        //该年为平年
            if(day > 28 || day < 1) {  //输入非法
            return false;
                }
            else {   //输入合法
            return true;
                }
                }
            }

    }
public static boolean isLeapYear(int year) {//判断year是否为闰年,返回boolean类型;

if(year%4 == 0 && year%100 != 0 || year%400 == 0 ) {  //为闰年
return true;
    }
else {   //为平年
return false;
    }
    }
}
​

 

 

 

其实还是跟之前的问题,之前老师说过java函数中最多有3到4个if-else,如何降低圈复杂度呢?

我到网上看了一下可以把if-else改成switch,当然这肯定是最简单的方法,我还知道一直那就是用数组来写,但这道题我只会改成switch。

PTA 7-3一元多项式求导(类设计)

心得:

这道题最后一个测试点其实是有问题的,就比如下面这个测试点

2x+2x

求导之后是 2+2,这个不难看出

但PTA 的标准是 22,它会把这个‘+’给去掉,如果你非要追求满分那就自己特判一下,当指数为0时,则不需要‘+’。

还有就是解这道题需要用到的几个函数

(1)substring()的用法

stringObject.substring(start,stop)

参数描述
start 必需,一个非负的整数,规定提取的子串的第一个字符在stringObject中的位置
stop 非需,一个非负的整数,比要提取的子串的最后一个字符在stringObject的位置多1。如果没给出该参数,那么返回的子串一直到该字符串的结尾。
例子:
package Main;
​
public class Test {
​
    public static void main(String[] args) {
        // TODO Auto-generated method stub
     String num = "hello world!";
    String num1= num.substring(1,7);
    System.out.print(num1);
    }
​
}
 

输出结果

ello w

 

运用该函数我们可以提取多位的整数,方便后面的转化

(2)BigInteger的用法

提取出子串之后就要把它转化成int型了,但这道题有一个大数测试点,完全超过了long的长度,就像老师说的一开始就应该想好会有哪些测试点,不然写完之后还要重头开始改

package Main;
​
import java.math.BigInteger;
​
public class Test {
​
    public static void main(String[] args) {
        // TODO Auto-generated method stub
     String num = "1011100111";
    BigInteger a = new BigInteger(num);
   System.out.print(a);
    }
​
}
​

 

输出结果:

1011100111

 

正常来说是 BigIntefer(str,radix) 如果你不写radix就默认转化为10进制。

以下为BigInteger的基本运算和比较大小的代码:

package Main;
​
import java.math.BigInteger;
​
public class Test {
​
    public static void main(String[] args) {
        // TODO Auto-generated method stub
    BigInteger a = new BigInteger("5");
    BigInteger b = new BigInteger("4");
    System.out.print("a = " + a);
    System.out.println("   b = " + b);
    int n=2;
 //加法
    BigInteger num1 = a.add(b);
    System.out.println("a + b = " + num1);
 //减法
    BigInteger num2 = a.subtract(b);
    System.out.println("a - b = " + num2);
 //乘法
    BigInteger num3 = a.multiply(b);
    System.out.println("a * b = " + num3);
 //除法
    BigInteger num4 = a.divide(b);
    System.out.println("a / b = " + num4);
 //取模
    BigInteger num5 = a.mod(b);
    System.out.println("[a/b] = " + num5);
 //求余
    BigInteger num6 = a.remainder(b);
    System.out.println("a % b = " + num6);
 //平方
    BigInteger num7 = a.pow(n);   //pow里面的n腰围int型
    System.out.println("a的" + n + "次方: " + num7);
 //取绝对值
    BigInteger num8 = a.abs();
    System.out.println("|a| = " + num8);
 //去相反数
    BigInteger num9 = a.negate();
    System.out.println("-a = " + num9);
 /*比较大小
compareTo()返回一个int型数据:1 大于; 0 等于; -1 小于;*/
    int num10 = a.compareTo(b);
    System.out.println(num10);
 //max(),min():分别返回大的(小的)那个BigInteger数据;
    BigInteger max = a.max(b);
    System.out.println("a和b哪个大:" + max);
    BigInteger min = a.min(b);
    System.out.println("a和b哪个小:" + min);
    }
​
}
​

 

输出结果:

a = 5   b = 4
a + b = 9
a - b = 1
a * b = 20
a / b = 1
[a/b] = 1
a % b = 1
a的2次方: 25
|a| = 5
-a = -5
1
a和b哪个大:5
a和b哪个小:4

基本上你会了这两个函数的运用再加上一些特殊条件的判断,这道题就可以写出来了。

我的代码很low,我写完之后才知道这两个函数可以这么用,我的是面向过程的写法,而且我没办法判断大数,可以说是想到什么就写什么的。

源代码:

package pta1;
import java.util.Scanner;
​
public class P3 {
    static Scanner in = new Scanner (System.in);
static  String num = in.nextLine();
 static String num1=num.replaceAll("\\s*", "");
static  long  [] b = new long [100];    //存入系数,指数,常数
static  int[] c = new int[100];    // 1为系数,2为指数,0为常数
static  char[] a = num1.toCharArray(); 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        int n;
        n = HJ(a,b);
        if(Checkb(b,n) == false){
            System.out.print("Wrong Format");
            System.exit(0);
        }
        QiuD(b,c,n);
        Print(b,c,n);
     }
    public static void Print(long b[],int c[],int n) {
        int i=0,cout=0;
        if(Check1b(b,n) == true) {
            System.out.print("0");
            System.exit(0);
        }
        System.out.print("\n");
        for(i = 0; i <= n; i++) {
            if(cout == 0 && c[i] == 1) {
                if(b[i] == 1 && b[i+1] != 0 && b[i+1] != 1)
                    System.out.print("x^" + b[i+1]);
                else if(b[i] == -1 && b[i+1] != 0 && b[i+1] != 1) {
                    System.out.print("-x^" + b[i+1]);
                }
                else if(b[i+1] == 0) {
                    System.out.print(b[i]);
                }
                else if(b[i+1] == 1) {
                    System.out.print(b[i] + "*x");
                }
                else 
                {
                    System.out.print(b[i] + "*x^" + b[i+1]);
                }
                i++;
                cout = 1;
            }
            else if(cout == 1 && c[i] == 1) {
                if(b[i] > 0 && b[i+1] != 0&&b[i+1] != 1) {
                    System.out.print("+" + b[i] + "*x^" + b[i+1]);
                }
                else if(b[i] > 0 && b[i+1] != 0 ){
                    System.out.print("+" + b[i] + "*x");
    }
else if(b[i] < 0 && b[i+1] != 0 && b[i+1] != 1) {
System.out.print(b[i] + "*x^" + b[i+1]);
    }

else if(b[i] < 0 && b[i+1] != 0 ) {
System.out.print(b[i] + "*x" );
    }
else if (b[i] > 0 && b[i+1] == 0) {
System.out.print("+" + b[i] );
    }
else if(b[i] < 0 && b[i+1] == 0)
System.out.print(b[i]);
i++;
    }
else if(c[i] == 0) {
if(cout == 1) {
cout = 1;
    }
else {
cout =0;
    }
    }
    }
    }
public static void QiuD(long b[], int c[] ,int n) {
int i,j=0;
for(i = 0; i <= n; i++) {
if(c[i] == 1) {
         b[i] = b[i]*b[i+1];
         i++;
         b[i] = b[i] -1;
    }
else if(c[i] == 0) {
b[i] = 0;
    }
    }
System.out.print("\n");
for(i = 0; i <= n; i++) {
System.out.print(b[i] + " ");
    }
    }
public static boolean Checkb(long b[] ,int n) {
int i;
for(i = 0; i <= n ; i++) {
if(b[i] == 0) {
return false;
    }
    }
return true;
    }
public static boolean Check1b(long b[] ,int n) {
int i;
for(i = 0; i <= n ; i++) {
if(b[i] != 0) {
return false;
    }
    }
return true;
    }
public static int HJ(char a[] ,long b[]) {
int i=0,cout = 1,j=0,check=1,k=0;    
int n,m;
m = num1.length();    //字符串长度
        while(i < m){
        if(a[i] == '-') {
       
        cout = -1;
        i++;
            }
        else if(a[i] == '+') {
        
        cout = 1;
        i++;
            }
        else if(a[i] == '1' || a[i] == '2' || a[i] == '3' || a[i] == '4' || a[i] == '5' || a[i] == '6' || a[i] == '7' || a[i] == '8' || a[i] == '9' || a[i] == '0') {
        n = a[i] - '0';
        if(check == 0 ) {
        j++;
            }
        b[j] = b[j]*10 + n;  
              check=1;
              i++;
              if(i == m)
              {
        b[j] = cout * b[j];
            System.out.print(b[j] + " ");
              }
        
                if(i < m  && (a[i] == '*' || a[i] == '+' || a[i] == '-')) {
                b[j] = cout * b[j];
                
           System.out.print(b[j] + " ");
            check = 0;
                }
               
​
            }
        else if(a[i] == '*' || a[i] == 'x' || a[i] == '^') {
        if(j !=0 && k == j-1)
        k = j;
        if(a[i] == '*') {
        
        c[k] = 1;
        
        k++;
            }
        if(a[i] == '^')
            {
        
        c[k] = 2;
        k++;
        
            }
        if(a[i] == 'x' &&  (i==0 || a[i-1] == '+' || a[i-1] == '-')) {
        if(i >=2 && a[i-2] == 'x')
        j++;
        b[j] = cout;
        System.out.print(b[j] + " ");
              
        c[k] = 1;
        k++;
        
            }
        if(a[i] == 'x'&&(i == m-1 || a[i+1] == '+'|| a[i+1] == '-')) {
        j++;
        b[j] = 1;
        System.out.print(b[j] + " ");
        
        c[k] = 2;
        k++;
            }
        cout =1;
        check = 0;
                i++;
            }
        }
System.out.print("\n");
        for(i = 0; i <= j; i++) {
        System.out.print(c[i] + " ");
        }
        return j;
    }

} 

 

 


 

总结:

通过这三次大作业,自己清晰地知道自己的代码可读性很低,基本只有自己能够看懂,复杂的问题没有用到类设计来解决,不够清晰,而且自己的代码圈复杂度太高,也学到了一些关于String的一些函数的用法,特别是对大数的处理,以后自己也能够很好的解决此类问题。

 

posted @ 2021-10-15 14:57  aimer1  阅读(49)  评论(0)    收藏  举报