pta题目集1~3的总结

前言:

一开始看到这个题目,感觉东西很多,不好下手,但深入探究下来,其实就是一个一个功能去做然后串联到一起就完成了。当然其中还是有一些技术难点的,下面会具体分析一些我遇到的难点,希望对你有所帮助。

题目集 1~3 的知识点、题量、难度等情况如下:

  • 知识点:JAVA基础语法,一些基础算法以及一些较高级的算法,面向对象程序设计

  • 题量:共 3 道

  • 难度:题目从易到难,具体来说,应该是越来越复杂,功能增多且判断格式愈加严谨

设计与分析:

该Blog 重点分析菜单计价系列题目,即题目集 2 的 7-1、7-2 以及题目集 3 的 7-1。这三个题目都具有典型的菜单计价特征,需要对菜单进行设计并实现相应的计价算法。

 

2-7-1:给出多个订单,计算指定菜品的组合总价。该题目主要是考察类的创建,输入数据格式的判断,以及方法的构造。该题目只需要构造两个类和一个方法便可以实现

   提示一下,这里写的大部分为静态方法,用静态可以少写一些代码,但是会有容易被修改的风险,工业化不能这样去写,还是要去封装,这里是为了应付作业才这样写。

 1 static class Dish {
 2         String name;
 3         int unit_price;
 4     }
 5 
 6 static class Record {
 7         int orderNum;
 8         Dish d;
 9         int portion;
10         int quota;
11 
12         int getPrice () {
13             if (portion == 2) {
14                 return (int) Math.round (1.5 * d.unit_price) * quota;
15             }
16             else if (portion == 3) {
17                 return 2 * d.unit_price * quota;
18             }
19             else {
20                 return d.unit_price * quota;
21             }
22         }
23     }
24
  • 2-7-2:给出一个菜单和多个订单,计算订单中菜品的组合总价。该题目主要是考察对类对象的访问以及成员变量的存储。在实现过程中,需要区分菜单信息和订单信息格式上的不同,以免发生方法调用上的错误。在7-1的基础上,本题需要设计方法来手动输入菜单信息,我选择构造一个新的类来实现这些方法
     
    static class Menu {
            Dish[] dishs = new Dish[20];
    
            int searchDish () {
            
            }
    
            Dish addDish () {
            
            }
        }

    其次,本题新增了对订单类的删改功能,同样,也是构造新的方法来实现这些功能

     
     1     static class Order {
     2         Record[] records = new Record[20];
     3 
     4         Record addARecord () {
     5                     }
    13 
    14         boolean delARecordByOrderNum () {
    15                    }
    30     }
     

     

  • 3-7-1:给出一个菜单和多个桌号信息,每个桌号包含多个订单信息,计算每桌订单中菜品的组合总价。该题目主要是考察类和方法的创建和使用,对变量的存储和访问。在实现过程中,需要区分菜单信息、桌号信息和订单信息格式上的不同,以免发生数据丢失。相比于上一次菜单题目,本次题目增添了table类,其中包含结账和增添新订单等操作(实际就是之前的Order类新增一些内部成员变量,但是写的时候没注意到就胡乱的增添了一个类)
     
     1 static class Table {
     2         Order order = new Order ();
     3         int num;
     4         int order_count = 0;
     5         LocalDateTime time;
     6         long sum = 0;
     7 
     8         void od (Menu menu, int menu_count, String str1, String str2, int portion, int quota) {
     9             if (str2.equals ("delete")) {
    10                 if (order.delARecordByOrderNum (Integer.parseInt (str1), order_count)) {
    11                     order_count--;
    12                 }
    13             }
    14             else {
    15                 if (menu.searchDish (str2, menu_count) != -1) {
    16                     order.records[order_count] = new Record ();
    17                     order.records[order_count] = order.addARecord (Integer.parseInt (str1), str2, portion, quota, menu_count, menu);
    18                     order_count++;
    19                 }
    20                 else {
    21                     System.out.println (str2 + " does not exist");
    22                 }
    23             }
    24         }
    25 
    26         void getSum () {
    27             int weekday = time.getDayOfWeek ().getValue ();
    28             for (int i = 0; i < order_count; i++) {
    29                 sum += order.records[i].getPrice ();
    30             }
    31             if (weekday > 0 && weekday < 6) {
    32                 if (time.getHour () >= 17 && time.getHour () < 20) sum = Math.round (sum * 0.8);
    33                 if (time.getHour () == 20) {
    34                     if (time.getMinute () <= 30) sum = Math.round (sum * 0.8);
    35                 }
    36                 if (time.getHour () >= 10 && time.getHour () < 14) sum = Math.round (sum * 0.6);
    37                 if (time.getHour () == 14) {
    38                     if (time.getMinute () <= 30) sum = Math.round (sum * 0.6);
    39                 }
    40             }
    41         }
    42 
    43         boolean isOpen () {
    44             int weekday = time.getDayOfWeek ().getValue ();
    45             if (weekday > 0 && weekday < 6) {
    46                 if (time.getHour () >= 17 && time.getHour () < 20) return true;
    47                 if (time.getHour () == 20) {
    48                     if (time.getMinute () <= 30) return true;
    49                 }
    50                 if (time.getHour () > 10 && time.getHour () < 14) return true;
    51                 if (time.getHour () == 10) {
    52                     if (time.getMinute () >= 30) return true;
    53                 }
    54                 if (time.getHour () == 14) {
    55                     if (time.getMinute () <= 30) return true;
    56                 }
    57             }
    58             else {
    59                 if (time.getHour () > 9 && time.getHour () < 21) return true;
    60                 if (time.getHour () == 9) {
    61                     if (time.getMinute () >= 30) return true;
    62                 }
    63                 if (time.getHour () == 21) {
    64                     if (time.getMinute () <= 30) return true;
    65                 }
    66             }
    67             return false;
    68 
    69         }
    70     }
     

     

采坑心得:

在提交源码的过程中,我遇到了很多问题,总结如下:

  • 对格式错误的数据的处理问题:在读入并判断输入数据格式时,要注意对错误格式的信息进行忽略并报错,否则会导致程序崩溃。
  • 数组下标越界问题:在删除订单信息时,要注意数组下标是否越界,否则会导致程序崩溃。
  • 对不同格式信息的区分问题:在读入数据后,格式的判断一定要严谨,否则会导致数据的丢失。
  • 类的结构过于混乱:在编写程序时一定要注意程序的结构是否可拓展和可读,避免后期维护产生问题。

主要困难以及改进建议:

在解题过程中,我遇到了以下主要困难:

  • 对时间类的使用不够熟练:在解决储存每桌对应的时间时,我发现测试样例中时间的格式不统一,时而是单数时而是双数,导致使用SimpleDataFormat(yyyy/MM/dd HH/mm/ss)
    的时候出现报错。
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH/mm/ss");
    Date date = new Date();
    date= sdf.parse(time);

     

  • 算法的实现不够高效:对于多桌菜的情况,处理大量数据时因为循环结构过多导致耗时很长,无法达到预期结果。
  • 代码能力有待提高:在解题过程中,我发现自己代码能力还有待提高,主要体现在代码的可读性和可维护性上,难以在原有的结构基础上拓展新的功能。因此,需要加强对编码技巧的掌握,提高代码的可读性和可维护性。

改进建议:

  • 对于时间类需要有更多的理解,在寻找上述中提到的时间格式问题的解决方法时,我在网络上领教到了一种较为方便的解决方法:

     将data类转化为Instant类,再由时区转换为LocalDateTime类,这样就可以避免因为输入格式的不统一而造成的错误了。

    1 Date date = new Date();
    2             date= sdf.parse(time);
    3             Instant instant = date.toInstant();
    4             ZoneId zone = ZoneId.systemDefault();
    5             tables[table_count].time= LocalDateTime.ofInstant(instant, zone);

     

  • 对于提高代码可拓展性上,我将原本的很多功能重构成了方法,也增加了类的使用频率,让代码整体的结构更加紧密和可拓展。
  • 对于格式的判断,我率先想到的就是判断数据的某个元素是否可以转化为数字,以将不同的数据分割开处理,因此,我构造了isNumeric方法来判断是否可以转化成数字
     
    1     public static boolean isNumeric (String string) {
    2         int intValue;
    3         try {
    4             intValue = Integer.parseInt (string);
    5             return true;
    6         } catch (NumberFormatException e) {
    7             return false;
    8         }
    9     }
     

    当然,这个方法并不是很好,一方面每个数据都要判断一遍导致运行速度大大降低,另一方面可扩展性不高,后期添加新的功能时需要大量改动原有代码。但当时不会更加高效的判断方法,也是无奈之举。

  • 针对删除订单信息的方法中出现的数组越界问题,我引用了新的计数变量count,来记录数组的长度,从而防止数组下标越界的问题(其实可以直接调用数组的length方法,只是当时忘了)
     
     1 boolean delARecordByOrderNum(int orderNum,int count){
     2             int i=0,j=0,flag=0;
     3             for(i=0;i<count;i++){
     4                 if(records[i].orderNum==orderNum){
     5                     for(j=i;j<count-1;j++){
     6                         records[j]=records[j+1];
     7                     }
     8                     flag++;
     9                 }
    10             }
    11             if(flag==0){System.out.println("delete error;");return false;}
    12             return true;
    13         }
     

     

仍未解决的问题:

  • 即使优化了代码的结构,代码的运行效率依旧达不到预期的水准,个人猜测是由于判断输入数据格式的方法太过笨拙。
  • 使用不可拓展容器来储存变量,有超出容器容量的风险,应当换用ArrayList、queue等容器。这样不仅可以解决容器大小的问题,也可以让数据的增删查改更加方便。
  • 胡乱的增加类以及静态变量的使用,导致类与类的关系变得混乱,应当将Table类与Order类结合起来,以增加代码的可读性。

总结:

现在回顾这几个题目感觉难度并不是很大,思路相对来说还算比较清晰,各种方法实现起来还算比较简单。但由于功能多,且判断输入格式是否正确的条件过多,这对于当时第一次接触两百行以上的项目的我来说无疑是个大挑战,我很庆幸自己可以突破这个难关,虽然使用的方法并不够好,用了许多“笨方法”来实现,代码的结构也不够清晰,可读性也比较差,不过通过这次综合性训练我学到了很多新知识。在此之前我对parse方法了解不多,也不知道LocalDateTime等日期类的一些使用方法。总体而言,这套菜单系统的练习让我学到了很多新知识,并且使我对代码结构的理解更加深刻,意识到了代码可拓展性的重要以及方法简化的重要性。

posted @ 2023-05-24 19:58  流年似水亦穆  阅读(39)  评论(0)    收藏  举报