题目集1~3的总结性Blog
前言:
这个月的java学习,让我们学会了很多东西,关于知识点的话,第一周是对java基础语法的学习,题 量稍大,但难度低,是很好的锻炼基础语法的题目,第二周则是对很多细节掌控的练习,各种情况的分析,还有就是对算法优化的问题,让我们有了复杂度这个模糊的概念。第二周难度中等,题量也是中等,不多不少刚刚好的那种。而第三周则是开始锻炼我们面向对象思维的开始,对类的编辑,初步了解了面向对象的编程方式,且初步学会使用了正则表达式去模拟字符串格式来查找字符串的子串,题量少,难度的话,对类的创建的题目则难度中等,正则表达式则难度较高,要学会正则表达式,还有对题目各个情况的分析。
设计与分析:
1.java学习第一周

概况: 第一周的话,普遍题目都比较简单,值得一谈的是7-8题,判断直角等腰三角形时有一点小坑;
| 题目 | 考察知识 | 难度 |
| 1.计算两个数的和 | 基础的输入即输出 | 基础 |
| 2.电话键盘字母数字转换 | 处理字符 | 基础 |
|
3.成绩分级管理 |
对判断switch语句的使用 | 基础 |
| 4.计算税率 | 对判断if语句的使用 | 基础 |
| 5.计算钱币 | 取余数和循环操作 | 简单 |
| 6.使用一维数组求平均值 | 基础的数组处理 | 简单 |
| 7.对多个整数进行排序 | 数组排序 | 简单 |
| 8.判断三角形类型 | 精度处理 | 较简单 |
主要给大家分析下第8题:
7-8核心代码(原判断条件的代码)
1 if(a<b) 2 { 3 temp=a; 4 a=b; 5 b=temp; 6 } 7 if(a<c) 8 { 9 temp=a; 10 a=c; 11 c=temp; 12 } 13 A=a*a; 14 B=b*b; 15 C=c*c; 16 if(b<1||c<1||a>200) 17 { 18 System.out.println("Wrong Format"); 19 System.exit(0); 20 } 21 else if((a>=b+c)) 22 { 23 System.out.println("Not a triangle"); 24 System.exit(0); 25 } 26 27 else if(a==b&&c==b) 28 { 29 System.out.println("Equilateral triangle"); 30 System.exit(0); 31 } 32 33 else if(A==B+C){ 34 if(c!=b) 35 { 36 System.out.println("Right-angled triangle"); 37 System.exit(0); 38 } 39 else 40 { 41 System.out.println("Isosceles right-angled triangle"); 42 System.exit(0); 43 } 44 } 45 else if(a==b||a==c||b==c) 46 { 47 System.out.println("Isosceles triangle"); 48 System.exit(0); 49 } 50 else{ 51 System.out.println("General triangle"); 52 System.exit(0); 53 }
但是呢,这样的代码会导致等腰直角三角形的测试点不能通过为什么呢!接下来我们来刨析一下:
刨析: 因为需要满足直角三角形的条件需要直角边等于斜边的根号2倍,而根号2是一个无理 数,导致double类型精度不够被约分,导致误差,于是我们只需要使斜边的平方减去斜边的平方的总结果取绝 对值小于较小的数据即可!!
改进后的代码如下:(仅仅改变了判断的内容)
if(b<1||c<1||a>200) { System.out.println("Wrong Format"); System.exit(0); } else if((a>=b+c)) { System.out.println("Not a triangle"); System.exit(0); } else if(a==b&&c==b) { System.out.println("Equilateral triangle"); System.exit(0); } else if(Math.abs(A-(B+C))<0.000001){ if(c!=b) { System.out.println("Right-angled triangle"); System.exit(0); } else { System.out.println("Isosceles right-angled triangle"); System.exit(0); } } else if(a==b||a==c||b==c) { System.out.println("Isosceles triangle"); System.exit(0); } else{ System.out.println("General triangle"); System.exit(0); }
简而言之也就是这句 if 语句:
else if(Math.abs(A-(B+C))<0.000001)
性能优化:优先把三边的中最长的一边找出,且计算出三边的平方,防止重复计算,达到优化的效果。
总体程序效果如下:

2.java学习第二周

概况:第二周的话,第四题和第五题稍微麻烦点。其余题目稍简单。
| 题目 | 考察知识 | 难度 |
| IP地址转换 | 处理字符串 | 简单 |
| 合并两个有序数组为新的有序数组 | 较为简单的数组处理 | 简单 |
| 判断闰年及星期几 | 基础语法的混合使用,函数 | 中等 |
| 求下一天 | 基础语法的混合使用,函数 | 中等 |
| 求前N天 | 基础语法的混合使用,函数 | 中等 |
1)7-4.
7-4核心代码(计算下一天):
public static void nextDate(int year,int month,int day) //求输入日期的下一天 { int[] qz = {0,31,28,31,30,31,30,31,31,30,31,30,31}; if(isLeapYear(year)&&month==2){ if(day==qz[2]+1){ System.out.println("Next date is:" + year + "-" + "3-1"); } else{ System.out.println("Next date is:" +year + "-" + month + "-" + (day+1)); } } else if(isLeapYear(year)&&month==12){ if(day==qz[12]){ System.out.println("Next date is:" + (year+1) + "-" + "1-1"); } else{ System.out.println("Next date is:" +year + "-" + month + "-" + (day+1)); } } else{ if(day==qz[month]){ if(month==12) System.out.println((year+1) + "-" + "1-1"); else System.out.println("Next date is:" + year + "-" + (month+1)+ "-1"); } else{ System.out.println("Next date is:" +year + "-" + month + "-" + (day+1)); } } }
刨析:主要是利用qz数组,其下标代表平年月份的天数,便于加一天的操作。
该程序具体的数据如下:

优化以及改进:使用数组去存储月份中的天数,且在计算下一天之前,判断输入日期是否合理,不合理即结束主函数。
2)7-5.
7-5核心代码(输出n天最后或者之前)
public static void nextDate(int year,int month,int day,int a) { int[] qz1 = {0,31,28,31,30,31,30,31,31,30,31,30,31}; //分别存储闰年和平年没过月份的天数 int[] qz2= {0,31,29,31,30,31,30,31,31,30,31,30,31}; if(a>0){ for(int i=0;i<a;i++) //利用for循环推进前一天或后一天,直到推至第n次。{ if(isLeapYear(year)){ //判断是否为闰年 if(day==1){ //考虑边界 month--; if(month==0){ //考虑边界 year--; month=12; } day=qz2[month]; } else day--; } else{ if(day==1){ month--; if(month==0) { year--; month=12; } day=qz1[month]; } else day--; } } } else{ for(int i=-a;i>0;i--){ if(isLeapYear(year)){ if(day==qz2[month]){ //考虑边界 day=1; month++; if(month==13){ //考虑边界 year++; month=1; } } else day++; } else{ if(isLeapYear(year)){ if(day==qz2[month]){ day=1; month++; if(month==13){ year++; month=1; } } else day++; } else{ if(day==qz1[month]){ day=1; month++; if(month==13){ year++; month=1; } } else day++; } } }
} System.out.println(a + " days ago is:" + year + "-" + month + "-" + day); //输出结果 }
刨析:使用循环进行加减日期,循环中套用多个判断达到输出前n天和后m天的效果。
该程序具体的数据如下:

心得:第五题相对与第四题,其复杂度大大升高,也许是因为循环的问题。过多的if判断镶嵌在循环里导致复杂度大大提升。
优化及改进:用swit语句可以减少很多没有必要的重复判断,循环可以写成一次性相加或者相减,可以省去很多时间。
3.java学习第三周
概况:第三周的话,都涉及到对类的设计,是锻炼我们基础的面向对象的思想,第三题则另外锻炼了我们对正则表达式的使用。

概况:第三周的话,第一题和第二题都是对类的创建,因为第二题写过类似的,所以相对简单,第三题则是这个月的重头戏,初步学习了正则表达式,并且使用,用于提取多项式中的单项式,难度较大。
| 题目 | 考察知识 | 难度 |
| 创建账户类Account | 创建基础的类 | 简单 |
| 定义日期类 | 基础的类知识 | 中等 |
| 一元多项式求导(类设计) | 正则表达式 | 难 |
主要给大家分析下第2题和第三题:
1)7-2.
对于类的设计:
7-2核心代码(Date类)
class Date{ private int year; private int month; private int day; public int getYear() { return year; } Date(){ } Date(int year,int month,int day) { //有参构造 this.year = year; this.month = month; this.day = day; } 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; } boolean isLeapYear(int year) { if((year%100!=0&&year%4==0)||year%400==0) return true; else return false; } boolean chaecklnputValidity(){ //日期是否合法 int[] qz = {0,31,28,31,30,31,30,31,31,30,31,30,31}; if(year<1900||year>2000) return false; else if(month<1||month>12) return false; else if(day<1||day>31) return false; else { if(month==2&&isLeapYear(year)){ if(day>qz[2]+1){ return false; } else return true; } else{ if(day>qz[month]) { return false; } else { return true; } } } } public void getNextDate() { //输出下一天 int[] qz = {0,31,28,31,30,31,30,31,31,30,31,30,31}; if(isLeapYear(year)&&month==2){ if(day==qz[2]+1){ System.out.println("Next day is:" + year + "-" + "3-1"); } else{ System.out.println("Next day is:" +year + "-" + month + "-" + (day+1)); } } else if(isLeapYear(year)&&month==12) { if(day==qz[12]){ System.out.println("Next day is:" + (year+1) + "-" + "1-1"); } else{ System.out.println("Next day is:" +year + "-" + month + "-" + (day+1)); } } else{ if(day==qz[month]){ if(month==12) System.out.println("Next day is:" + (year+1) + "-" + "1-1"); else System.out.println("Next day is:" + year + "-" + (month+1)+ "-1"); } else{ System.out.println("Next day is:" +year + "-" + month + "-" + (day+1)); } } }
刨析:主要是利用Date类里的函数中的qz数组,其下标代表平年月份的天数,便于加一天的操作。难度不大,和第二周的第二题相似。
该程序具体的数据如下:


优化以及改进:判断条件多使用switch语句。
1)7-3.
7-3核心代码(正则表达式)
String s = in.nextLine();
s1 = s.replace(" ","");; //去除空格
String zz1 = "([-+]?\\d*\\*?x(\\^-?\\d*)?)"; //单项式的正则表达式
Pattern pattern1 = Pattern.compile(zz1);
Matcher matcher1 = pattern1.matcher(s1);
boolean yes = matcher1.find();
while(yes) { //寻找单项式并存入dxs字符串中
dxs[x]=s1.substring(matcher1.start(), matcher1.end());
x++;
yes = matcher1.find();
}
核心代码(判断输出部分)
if(x==0) //判断系数和幂是否为都为整数的情况 { System.out.print("0"); System.exit(0); } for(int i=0;i<x;i++) { //存入系数和幂 if(dxs[i].contains("*")) xs[i] = zh(dxs[i]); else { if(dxs[i].charAt(0)=='-') xs[i]=-1; else xs[i]=1; } if(dxs[i].contains("^")) { int a = (dxs[i]).indexOf("^"); String str =dxs[i].substring(a + 1); mi[i] = zh(str); } else //如果系数或者幂为0及输出非法输入 mi[i]=1; if(xs[i]==0||mi[i]==0){ System.out.print("Wrong Format"); System.exit(0); } } for(int i=0;i<x;i++) { String z = ss(xs[i],mi[i]); if(i==0) { //判断当i为0的特殊情况 if(mi[i]*xs[i]==1) { if(mi[i]==1) { //判断幂为1的情况 System.out.print("1"); } else if(mi[i]==2) { //判断幂为2的特殊情况 System.out.print("x"); } else { System.out.print("x^" + (mi[i]-1)); } } else if(mi[i]*xs[i]==-1) { if(mi[i]==1) { System.out.print("-1"); } else if(mi[i]==2) { System.out.print("-x"); } else { System.out.print("-x^" + (mi[i]-1)); } } else { if(mi[i]==1) { System.out.print(z); } else if(mi[i]==2) { System.out.print(z + "*x"); } else { System.out.print(z + "*x^" + (mi[i]-1)); } } } else { if(mi[i]==1) { System.out.print(z); continue; } else if(z.charAt(0)=='-') ; else System.out.print("+"); if(mi[i]*xs[i]==1) { if(mi[i]==1) { System.out.print("1"); } else if(mi[i]==2) { System.out.print("x"); } else { System.out.print("x^" + (mi[i]-1)); } } else if(mi[i]*xs[i]==-1) { if(mi[i]==1) { System.out.print("-1"); } else if(mi[i]==2) { System.out.print("-x"); } else { System.out.print("-x^" + (mi[i]-1)); } } else { if(mi[i]==1) { System.out.print(z); } else if(mi[i]==2) { System.out.print(z + "*x"); } else { System.out.print(z + "*x^" + (mi[i]-1)); } } } }
核心代码(高精度算法)
public static String ss(long a,long b) { int[] a1 = new int [30]; int[] b1 = new int [30]; int[] cj = new int [30]; int js1 = 0 , js2 = 0,js=0; if(a>0) //判断正负 ; else { a=-a; js++; } if(b>0) ; else { b=-b; js++; } for(int i=0;i<30;i++) { if(cj[i]>9) { cj[i+1] = cj[i+1] + cj[i]/10; //存储 cj[i] = cj[i]%10; } } while(a!=0) { a1[js1] = (int) (a % 10); a = a/10; js1++; } for(int i = 0; i<30;i++) cj[i] = 0; while(b!=0) { b1[js2] = (int) (b % 10); b = b/10; js2++; } for(int i = 0; i < js2;i++) { //高精度处理 for(int j = 0;j < js1;j++) { cj[j+i] = cj[j+i] + b1[i] * a1[j]; if(cj[j+i]>9) { cj[j+i+1] = cj[j+i+1] + cj[j+i]/10; cj[j+i] = cj[j+i]%10; } } }
刨析: 为了取得这个题目的满分可谓路途多舛,首先是单项式的提取,多项式经过多次变换才得到最终的这个,然后是判断条件,系数和幂都是很麻烦的部分,要单独考虑没用数字的系数(即‘-’或者‘+’),还得考虑系数为0的非法输入,幂为0的非法输入,幂为1输出整数,幂为2不输出幂次的多种情况,最难的也许就是大数测试这个点,这个数据可以使得long类型爆掉,所以需要使用高精度算法,且返回方式应当为字符串,进一步增加了这个题目的难度。
该程序具体的数据如下:


优化以及改进:判断输出部分时,第一次输出为特殊情况,可以把其拿出来单独运行,可以减少for循环中多余的判断i是否为0。判断条件繁琐,且存在判断单个字符时没用使用switch。高精度算法在java中已经封存好了,可以直接使用。
采坑心得:
1.第一周7-8题的double精度不够。
2.第二周7-4题求下一天没用考虑跨年的情况。
3.第二周7-5题依旧没用考虑跨年的情况。
4,.第三周7-3题使用next()函数无法接受空格。
5.对正则表达式的+,*,?的使用不够灵活。
6.第三周7-3题大数测试点long范围不够。
改进建议:
1.多使用switch语句,其为比对单个字符,而if语句问匹配整体,效率差距巨大。
2.使用for会使得复杂度大幅度增加,在for语句中应当减少不必要的语句。
3.java中封装了很多实用的包,可以使用其里面的函数,多数可以做到比自己写一个的效果好,且方便。
4.多写注释且需要注意格式,当程序大起来时,其作用就愈发重要。
5.采用面向对象的思维来解决问题,可以把大问题解析为很多个小问题,且思路清晰,目标明确,耦合性低,容易修改。
6.第三周7-3题判断输出部分时,第一次输出为特殊情况,可以把其拿出来单独运行,可以减少for循环中多余的判断i是否为0。
总结:
这个月可谓学到了很多的知识,我充分认识到自己对于Java的了解还只是冰山一角,Java包含的内容十分丰富,我应该在日常的学习中不断
拓展,丰富自己在此领域了解的内容。我们锻炼了自己的自学能力,以及上网查询资料的能力,仅仅在一个星期就已经可以灵活运用java的基础
语法且初步体验到了面向对象的处理事情的方法,把复杂问题简单化,学会了创建类,使用类里的函数,理解了各个类之间的关系,懂得了什么
时候应该去创建类,把问题分解。并且学到了从未接触的正则表达式,触摸到了我从未接触的东西,题目很具有挑战性,很大程度的锻炼了我们
的能力,平时课程为线上线下双教学模式,是我们从未接触的上课方式,老师上课讲的东西更具有针对性,可以自学的都会让我们自己去学习,
唯独困难的,不易理解的才会讲,对我们的作业有启发。而课下也是需要自己去钻研,锻炼了我们要有不怕累,不怕苦的精神,这个月不仅仅是对
java的学习,更是对我们的磨砺!

浙公网安备 33010602011771号