5-7习题集blog
本次题目集5~7涵盖了Java面向对象编程的多个重要知识点,包括类设计、继承与多态、正则表达式、异常处理以及算法实现等。题目难度有简单的也有难的,题量适中但综合性较强,特别是电梯题目在三次题目集中都有出现,渐渐的提高了难度和要求。
题目集5主要考察基础编程能力,如身份证校验位计算、一元二次方程求解等;题目集6重点测试类设计能力,特别是单一职责原则的应用;题目集7则在前两次基础上增加了更复杂的场景模拟和算法实现。整体来看,这些题目很好地检验了我们对Java面向对象编程的理解和应用能力,除了电梯程序外其他的难度都不是很高,我都能比较轻松的解决
设计与分析
题目集5分析
5-1 身份证号校验位计算
这个题目要求根据身份证前17位计算校验位。实现思路是:
- 验证输入是否为17位数字
- 定义系数数组和校验码映射数组
- 计算加权和并取模得到校验位
int[] a1 = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
char[] a2 = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
int sum = 0;
for (int i = 0; i < 17; i++) {
sum += (input.charAt(i) - '0') a1[i];
}
int r = sum % 11;
char a2v = a2[r];
SourceMonitor分析显示该代码复杂度较低,方法平均复杂度为1.0,符合要求。

5-2 一元二次方程求解
这个题目要求设计一个QuadraticEquation类来求解一元二次方程。我按照题目要求实现了所有必要的方法:
class QuadraticEquation{
private double a;
private double b;
private double c;
public QuadraticEquation(double a, double b, double c){
this.a = a;
this.b = b;
this.c = c;
}
public double getDiscriminant(){
return b b - 4 a c;
}
public double getRoot1(){
return (-b + Math.pow(getDiscriminant(), 0.5)) / (2 a);
}
// 其他方法...
}

5-3 验证码校验
这个题目要求验证输入字符串是否为4位数字或字母。我的实现使用了字符数组遍历:
for(int i=0;i<ch.length;i++){
if(!((ch[i]>='0'&&ch[i]<='9')||(ch[i]>='a'&&ch[i]<='z')||(ch[i]>='A'&&ch[i]<='Z'))){
System.out.printf(new String(ch) + "不属于验证码");
return;
}
}
虽然实现了功能,但使用正则表达式应该会更简洁高效。

题目集6分析
6-1 点与线类设计阿
这个题目要求设计Point和Line类来表示坐标系中的点和线。我的实现如下:
class Point{
private double x;
private double y;
public Point(double x, double y){
this.x = x;
this.y = y;
}
public void display(){
if (x<=0||y<=0||x>200||y>200){
System.out.println("Wrong Format");
}
else{
System.out.printf("(%.2f,%.2f)",x,y);
}
}
// 其他方法...
}
class Line{
private Point p1;
private Point p2;
private String color;
public double getDistance(){
return Math.sqrt((p1.getX()-p2.getX())(p1.getX()-p2.getX())+
(p1.getY()-p2.getY())(p1.getY()-p2.getY()));
}
// 其他方法...
}
SourceMonitor分析显示代码复杂度适中,方法平均复杂度为1.5。类设计符合题目要求,但可以进一步优化异常处理。

6-2 汽车雨刷问题
这个题目要求设计多个类来模拟雨刷控制系统。我按照单一职责原则设计了Lever、Dial、Brush和Agent类:
class Lever {
private int pos;
public void upPos() { if (pos < 4) pos++; }
public void downPos() { if (pos > 1) pos--; }
// 其他方法...
}
class Agent {
private Lever lever;
private Dial dial;
private Brush brush;
public void dealSpeed() {
int leverPos = lever.getPos();
int dialPos = dial.getPos();
int speed = 0;
if (leverPos == 1) speed = 0;
else if (leverPos == 2) {
switch (dialPos) {
case 1: speed = 4; break;
case 2: speed = 6; break;
// 其他情况...
}
}
// 其他逻辑...
brush.setSpeed(speed);
}
}
SourceMonitor显示方法平均复杂度为2.0,处于合理范围。

6-3 单部电梯调度程序(类设计)
这个题目是前次电梯程序的迭代版本,要求按照更严格的类设计原则实现。由于难度较大,我未能完成全部功能,但可以分析理想的设计方案:
- 应该设计Elevator、Request、RequestQueue和Controller类
- Elevator类负责电梯状态管理
- Request类封装请求信息
- RequestQueue管理请求队列
- Controller协调电梯运行
class Elevator {
private int currentFloor;
private Direction direction;
private State state;
// 其他属性和方法...
}
class Request {
private int floor;
private Direction direction;
// 其他方法...
}
class Controller {
private Elevator elevator;
private RequestQueue queue;
public void processRequests() {
// 处理请求队列逻辑
}
}
题目集7分析
7-1 销售步枪问题
这个题目要求设计销售订单类计算销售额和佣金。我的实现:
class SalesOrder{
private int lockNum;
private int stockNum;
private int barrelNum;
public double getTotal(){
return lockNum45 + stockNum30 + barrelNum25;
}
public double Commission(double sales){
if(sales <=1000) return 0.1sales;
else if(sales <=1800) return 100 + 0.15(sales-1000);
else return 220 + 0.2(sales-1800);
}
}
SourceMonitor分析显示方法平均复杂度为1.8,结构清晰。类设计符合单一职责原则。

7-2 蒙特卡罗方法求圆周率
这个题目要求使用蒙特卡罗方法估算π值。我设计了Coordinate、Rectangle、Circle和MonteCarloSimulation类:
class MonteCarloSimulation{
public double simulation(int n){
double sum = 0;
for(int i = 0;i < n;i++){
double x = random.nextDouble()rectangle.getLength()+rectangle.getCoordinate().getX();
double y = random.nextDouble()rectangle.getWidth()+rectangle.getCoordinate().getY();
if(getDistance(new Coordinate(x,y),circle.getCoordinate()) <= circle.getRadius()){
sum+=1;
}
}
return 4sum/n;
}
}
该方法复杂度为2.0,算法实现正确,但可以优化随机数生成效率。

在题目集5~7中,单部电梯调度程序是贯穿三次题目集的核心题目,其设计难度和复杂度逐步提升。以下是对该题目的深入分析与设计思考:
题目集5的单部电梯调度程序
初次接触电梯调度问题时,我设计了一个简单的电梯类,将所有功能集中在一个类中,导致代码臃肿且难以维护。例如,电梯的状态管理、请求队列处理和调度逻辑全部混杂在一起。虽然功能勉强实现,但代码的可读性和扩展性极差。SourceMonitor分析显示,该类的平均方法复杂度高达3.5,远超合理范围(理想值应小于2.0)。以下是部分问题代码:
class Elevator {
private int currentFloor;
private List
private List
// 其他属性和方法...
public void processRequests() {
// 处理内部和外部请求的逻辑混杂
}}
题目集6的电梯设计
在题目集6中,题目要求遵循单一职责原则,将电梯调度程序拆分为多个类。根据pta上面作业的示意图可以分为以下几类,
Elevator类:管理电梯的当前状态(楼层、方向、运行状态)。
Request类:封装乘客请求(楼层和方向)。
RequestQueue类:管理请求队列,处理请求的添加和过滤(如忽略重复请求)。
Controller类:负责调度逻辑,协调电梯运行。
改进后各类的方法平均复杂度降至1.8,代码结构更清晰。例如,Controller类的核心方法processRequests的复杂度从4.2降至2.1,逻辑更专注:
class Controller {
public void processRequests() {
while (!queue.isEmpty()) {
Request request = queue.getNextRequest();
elevator.moveTo(request.getFloor());
if (elevator.shouldStop(request)) {
elevator.openDoor();
elevator.closeDoor();
}
}
}}
题目集7的进一步修改
PTA题目集7-3要求加入乘客类,并将外部请求格式改为<源楼层, 目的楼层>。这样加大了题目的难度,可以这样设计:
Passenger类:新增乘客信息。
Request类:关联乘客和请求信息。
逻辑优化后,当电梯处理外部请求后,将会自动将目的楼层加入内部队列。
这一阶段主要在于内外请求的动态管理。比如说,当电梯处理<5,9>请求时,需要在到达5楼后,将9楼加入内部队列。以下是我修改后的主要信息:
class RequestQueue {
public void addExternalRequest(Passenger passenger, int source, int target) {
Request externalRequest = new Request(passenger, source, Direction.UP); // 假设方向需计算
Request internalRequest = new Request(passenger, target, null); // 内部请求无方向
externalRequests.add(externalRequest);
internalRequests.add(internalRequest);
}}
采坑心得
- 身份证校验位计算:最初忽略了输入长度检查,导致程序可能接受非法输入。通过添加长度验证解决了问题:
if (input.length() != 17) {
System.out.println("Wrong Format");
return;
}
- 一元二次方程求解:在计算判别式时,最初没有考虑浮点数精度问题,导致比较结果不准确。改进后使用了更精确的比较方式:
if (Math.abs(discriminant) < 1E-6) { // 视为等于0
// 处理单根情况
}
- 验证码校验:最初使用字符数组遍历判断,后来意识到使用正则表达式会更简洁:
if (input.matches("[0-9a-zA-Z]{4}")) {
// 验证码有效
}
- 点与线类设计:在坐标范围验证时,最初只检查了大于0的条件,忽略了上限200的限制。修正后:
if (x<=0 || y<=0 || x>200 || y>200) {
System.out.println("Wrong Format");
}
-
汽车雨刷问题:在实现Agent类时,最初将速度计算逻辑放在了错误的位置,导致状态更新不及时。通过重构将速度计算移到dealSpeed方法中解决了问题。
-
蒙特卡罗方法:在验证矩形是否为正方形时,最初使用==比较浮点数,导致精度问题。改进后:
if (Math.abs(length - width) < 1E-6) {
// 视为正方形
}
改进建议
-
性能优化:比如说在PTA上求π的题目中,可以优化随机数的生成,可以使用更高效的算法这样可以让运行更流畅不会卡顿
-
增加状态更新的功能:电梯程序中可以使用枚举的方法来管理电梯的不同状态,这样可以让当前状态更清晰。
-
加入日志调试:在电梯的程序中添加调试代码,这样可以便于找出问题所在。
-
文档注释:可以在一些关键地方增加一写注释来提高可读性,这样可以更容易看懂代码
总结
经过这三次题目集的练习,我可以理解了面向对象编程的基本原则和设计思想,尤其是是单一职责原则的重要性。在实现复杂系统如电梯调度程序时,良好的类设计能够大大降低代码复杂度,提高可维护性。
我掌握了以下关键技能:
- 类设计与实现
- 封装与信息隐藏
- 算法设计与实现
- 输入验证与异常处理
5.学会了 java的基本逻辑
可以进一步学习的领域:
- 设计模式的深入应用![]
- 多线程编程
- 更复杂的算法设计与分析
对课程的建议:
- 可以降低作业的频率和难度
- 可以让我们学生协作编程
完成题目后,这三次题目集让我在学习Java方面有了很大的进步,虽然遇到了很多问题,但经过写完这些题目后,我学到了很多宝贵的经验和学习java的方法
浙公网安备 33010602011771号