拿着代码往里打

导航

题目集4~6作业总结

题目集4~6的总结性Blog

        在本次pta题目集4-6的作业中,我们通过创建类,创建对象,创建类中方法,以及正则表达式的运用、继承、接口等方法成功实现了代码。前两次作业虽然题目量较小,但难度却比较的大。其中均存在对正则表达式的运用且十分复杂。到第六次作业难度便有了下降,其中题目复杂程度较低,同时也出现了新的知识点接口、继承和多态。虽然可能不是很熟练,但在这里我想把我自己的做法写出来,供大家参考。

       本次作业分为以下部分,三次作业实现介绍(包括调度方法), 总结作业。请读者各取所需。

     (注:本次作业算法仅针对作业题目,对实际情况并不完全相符)

 

一、三次作业的实现(设计与分析)

     1. 本次题目集4(7-2)、题目集5(7-4)两种对日期类聚合设计尤其使我印象深刻,原因是它们的算法几乎相似,但各类之间的关系却不同。

     

       其实这两题作业是面相对象的一种处理,过程也是比较的繁琐。

       在求下n天和前n天的时候,需要重点考虑月与年的变化,其中年的变化有需要考虑到平闰年的变化,其次月的变化便需要考虑到2月的总天数的变化。同时在求两日期相差的天数时,也需要考虑到这些,如果前面对这些过程考虑的比较完善,那么在求日期相差天数时便十分轻松了。

      虽然要求的答案和方向是一致的,但是类图却十分不同,所以我们先来看看它们的类图(我们在此将它们命名为第一种算法和第二种算法):

 

 聚合一:

 

 聚合二:

 

      我们不难看出第二中算法中Year类、Month类、Day类中相较于第一种算法之间无关联,这就使得我们在计算前N天和下N天时的算法不同 ,在此我附上两种求下N天的算法:

 

         public int getnumber(DateUtil date) {
             int c=0;
             if(comparedate(date)==true) {
                 while(comparedate(date)==true) {
                      day.DayIncrement();
                      c++;
                      
             }
                 return c;
         }
 public int getnumber(DateUtil date) {
         int c=0;
         if(compare(date)==true) {
             while(compare(date)==true) {
                  day.dayIncrement();
                if(day.getValue()>monthdayget()) {
                    day.setValue(1);
                    month.monthIncrement();
                    if(month.getValue()>12) {
                        year.yearIncrement();
                        month.setValue(1);
                        day.setValue(1);
                    }
                }
                c++;
         }
             return c;

       由于第一种算法中Year类、Month类、Day类是层层相关的,所以在天数加一的算法中同时包含了月份加一的算法,月份加一的算法中包含了年份加一的算法,这就使得在求下N天时只需要将天数加一加到N为止即可,但第二种算法钟Year类、Month类、Day类都聚合于DateUtil类种,就需要在内部考虑月的变化与年的变化。

 

       为方便比较两种算法的优劣势,我为大家提供两种的圈复杂图(按顺序):

 

 

 

   我们不难看出相较于第一种算法,第二种算法的圈复杂度更为简单,但是在重要类中的算法却较为复杂,却第二种算法运行时间较长,对大数据不敏感。

 

 

  2. 题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计:

      这三题都运用继承设计,其中(7-6)更是运用到了接口与多态的使用,初写时还是十分的艰难,但掌握之后便十分轻松,我们来看看。

      题目集4(7-3)可以说是最简单的继承类题目,它只是将方法定义在了一个Shape类中,然后在其它类中继承它,然后调用方法。我们来看看对其继承的部分代码:

 

class Circle extends Shape{
......
}
class Rectangle extends Shape{
......
}

在主函数中想要调用这些类的方法只需要创建相应的对象即可(本题较简单便不多做分析).

 

 

       题目集6(7-6)是便运用到了需要之前未使用过的知识,如:接口,多态。当然本题和上一题一样也是求面积和体积。经过分析发现其中便要求创建一个GetArea的接口,然后在各个图形类中对其实现继承,从而达到创建多态的效果。就下面代码我们来做分析:

interface getarea{
    public double getarea();
}

首先我们先创建获得面积的接口,并在接口中创建一个抽象方法。

class Circle implements getarea{
......
}

再让各个图形对此接口连接形成多态,最后在主类中创建对象调用即可。同时我们也可以看看本题的圈复杂度(如下图):

 

 

 

       题目集6(7-5)是这三题中最难的一题,其中不仅包含了继承、接口和多态的使用,还需要使用ArrayList创建list实行调用。

       在写本题时有一个难点,便是如何对数据进行添加和排序,经过多方资料的查询,我也得出了小结论,不多说看源码:

ArrayList<Double>list=new ArrayList<>();
...
list.add(one.getarea());
...
Collections.sort(list);

运用list.add()方法对list中数据进行添加,然后再对List进行排序即可。

       其中还有一个难点便是抽象类的使用,首先创建抽象类Shape,并在其中定义抽象方法,方便在对此抽象类的继承时调用抽象方法:

abstract class Shape{
    public abstract double getarea();
    public abstract boolean validate();

}

其他的操作方法基本与第一题和第二题一致,便不多做解释,下面我们来看看其圈复杂度:

 

可以看出此圈的复杂程度也是比较大的,主要体现在list的算法中,以及添加add()和得到get()的for循环算法中。

 

3. 对三次题目集中用到的正则表达式技术的分析总结:

 

       三次实验中群使用到了正则表达式,且难度程度较高,下面我们就部分题目进行分析:

(1).首先是题目集6(7-3),其中运用到的正则表达式为最为基础的表达式,此题要求我们对验证码进行匹配(验证码是由四位数字或者字母组成的字符串),下面我们来看看此题部分源码:

        String b="(^[A-Za-z0-9]+$){4}";
       boolean c=a.matches(b);

      首先我们创建一个匹配验证码的字符串,然后运用java中的matches进行匹配,即可得出结果。

 

(2).再拿较难的题目集4(7-1)进行分析,下面附上部分正则表达式源码:

String regex2 = "([\\S]+[ ])([\\S]+)[\t]([\\S]+)[\t]([\\S]+)[\t]([\\S]+[/][\\S]+)[\t]([\\S]+)";
......
String monthandday1 = "([123456789][/][1-9])|([1][0][/][1-9])|([1][1][/][1-9])|([1][2][/][1-9])";//月份的1-9日

      我们来看这个代码表现了对一串水纹数的字符进行匹配的正则表达式,以及对每个月的1-9日的匹配,关键点还是要对"|"和"//"的运用需要十分娴熟。

 

经过了这三次作业的正则表达式训练,我仿佛掌握了正则表达式的规律运用,就好比对一串特殊字符的正则表达式的书写以及对正则表达式的分割操作,在写正则表达式有关的题目时,还是需要灵活运用spilt(),matches(),以及pattern等技术方法,方能将正则表达式灵活运用。

 

 

4. 题目集5(7-4)中Java集合框架应用的分析总结:

 

      本题运用的依然时正则表达式,只不过是在运用正则表达式的基础上还附加运用了ArrayList的操作方法,使得解题更加方便。

本题所需要求的是关键字搜索,对Java中关键字的搜索,我们便可以很简单的创建一个关于关键字的字符串数组:

String [] gjz ={ "abstract","assert","boolean","break","byte","case","catch",             "char","class","const","continue","default","do","double","else",             "enum","extends","false","final","finally","float",         "for","goto","if","implements","import","instanceof",

接着我们在对输入的源码中的符号进行筛选:

for(int i = 0;i < 53;i++) {
            Pattern pattern = Pattern.compile("[(),.;\\n\\[:\\] \\r]"
                    + list1.get(i) + "[;\\[\\] .\\n,:())\\r]");
            int z = 0;
            for(int j = 0;j < str2.length;j++) {
                String[] str3 = str2[j].split("//");
                StringBuilder str_1 = new StringBuilder();
                str_1.append('\n');
                str_1.append(str3[0]);
                str_1.append('\n');
                Matcher matcher = pattern.matcher(str_1);
                while(matcher.find()) {
                    z++;
                }
            }
            list2.add(z);
        }

如这一段便是为了进行筛选含有“//”后面的注释和开头,这样后面便可以更好对字符串进行筛选了。

       其实本题运用到的框架主要还是对ArrayList的运用,以及部分的正则表达式分割,但对于我这个初学者来说难度确实是很大。

 

二、采坑心得

(1).在编写题目集5(7-5)的过程中,发现运行的代码始终是处于超时状态的,本来以为是PTA程序的出错,后面经过分析发现是自己的代码算法存在部分问题,导致运行结果一直超时。

我们就来看看我原来的代码吧:

if(compare(date)==false) {
             while(compare(date)==false) {
                   day.dayReduction();;
                if(day.getValue()<1) {
                    if(month.getValue()==3) {
                        month.setValue(2);
                        if(year.isLeapYear()==true) {
                            day.setValue(29);
                        }
                        else {
                            day.setValue(28);
                        }
                    }
                    else {
                    month.monthReduction();
                    day.setValue(monmaxnum[month.getValue()]);
                    if(month.getValue()<1) {
                        year.yearReduction();
                        month.setValue(12);
                        day.setValue(31);
                    }
                }
                }
                   c++;
                   if(same(date)==true) {
                       break;
                   }
          }
             return c;
         }
         else 
             return 0;
}

可以看到这是一个判断两日期相差天数的代码,但由于日期加减一时对年月的过分补充,导致代码变得十分复杂,很难在规定的时间内运行。

本题心得:在编写代码时,需要考虑到代码的运行量以及运行时长以更加方便的运行,有时候简单的几行代码往往比for循环来的要快一点。

 

(2).在写题目集6(7-5)时,经常遇到十分变扭的报错:

就拿这个为例,在创建抽象类中的抽象方法时,始终存在报错的情况,后经过改进才发现问题。

本题心得:抽象类中的抽象方法不需要补全完整,只需要创建抽象方法即可,连花括号都不需要打入。

 

(3).题目集6(7-2)中,对字符串按ASCII码进行升序排序并输出,其实刚开始写到这一题的时候我人是懵的,由于上个学期没有学好,对ASCII码并不了解,所以就十分的困扰,不知改怎么下手,但后来经过寻求多位大佬的帮助,成功将其理解:

        String a=in.next();
        char []b=a.toCharArray();
        Arrays.sort(b);

本题心得:对字符串进行一些特殊排序可以将其转化为字符串组在运用sort进行排序。

 

三、改进意见

(1).就拿采坑心得中的第一个为例,对于超时的代码改进,有时候简单的几句话往往比for循环来的更加的直接,可能在写题目时,我们不会经常性的注意时长,但是在实际生活的运用中,时长还是十分重要的,以后编码也会更加的注重算法和群复杂度,争取让自己以最简单的代码写出最快的过程。

 

(2).有时对于正则表达式的题目还是不能灵活运用spilt(),matches(),等操作方法,而去用ArrayList的方法去慢慢匹配,导致自己吃了许多的亏,自己一定要在以后写此类题目的时候将正则表达式中的一些方法灵活运用,来减小代码的复杂程度。

 

(3).碰到继承与多态的题时,经常回去创建抽象类以及抽象方法,但是每次抽象方法都不能做到精简,以至于在后面类的继承中,每次继承都需要对抽象类中的抽象方法进行补全,过程便十分繁琐,以后会对抽象类中的抽象方法做到更加的精简,让后面的代码实现起来更加轻松。

 

四、总结

       本次作业我学习到了继承、多态以及接口的运用,正则表达式的运用和ArrayList的运用,成功掌握了正则表达式中的多种使用方法。但是,我还有许多地方有待进步和改进,比如对于正则表达式的难点题目的突破和ArrayList创建对象List的运用等。其它的各种方法我也会抓紧时间去学习。

       对于老师的讲学方式我也是比较喜欢的,以腾讯课堂展示,让我们能更好的,更清楚的看清代码以及一些知识。同时呢也希望以后的作业题目集难题能稍微少一些,实验的难度也可以稍稍降低些。

       最后,感谢罗老师对我们的指导教学,同时呢也感谢xyh,zs等大佬的帮助与鼓励。

       大家一起加油吧!

 

posted on 2021-04-26 20:43  拿着代码往里打  阅读(44)  评论(0编辑  收藏  举报