题目集5~7的总结性Blog

(1)前言:
在本次课程的学习进程中,题目集 5、6、7 如同三座各具特色的山峰,等待着我们去攀登与征服。这三次题目集涵盖了丰富多样的知识点,题量分布合理,难度层次分明,逐步引导我们深入理解和掌握相关编程技能与算法思维。
题目集 5 主要聚焦于基础算法的应用与简单类的设计。其题量适中,包含 5 道题目,难度处于入门向进阶过渡的阶段。大部分题目旨在让我们熟悉基本的数据结构操作以及流程控制语句的运用,为后续更复杂的编程任务奠定坚实基础。例如,其中涉及到数组的排序与查找问题,通过这些题目,我们不仅巩固了数组这一基础数据结构的使用,还学会了如何根据不同的需求选择合适的排序与查找算法,如冒泡排序、二分查找等。
题目集 6 在题目集 5 的基础上进行了知识的拓展与深化,引入了面向对象编程的更多概念和技巧。 3 道,难度也提升至中等水平。在这一题目集中,类的继承、多态以及接口的使用成为重点考察内容。比如,通过设计一系列具有继承关系的图形类,我们深刻体会到了如何利用继承来实现代码的复用,以及如何通过多态性来实现不同对象的差异化行为,极大地提升了我们对面向对象编程思想的理解与运用能力。
题目集 7 则更加注重综合应用能力与算法优化。题量维持在 3 道,难度达到了较高水准。它要求我们将之前所学的各种知识进行融会贯通,解决一些实际场景中的复杂问题。例如,在涉及到复杂数据处理与算法优化的题目中,我们需要综合运用数据结构、算法设计以及面向对象编程等多方面知识,设计出高效、可维护的解决方案,这对我们的编程综合素养提出了极高的挑战。
(2)设计与分析
题目集5-1:

1. 输入处理:使用合适的输入方式(如 Java 中的 Scanner )获取用户输入的身份证号前 17 位字符串。对输入字符串的长度进行检查,若长度不为 17 则判定为输入格式错误,输出相应提示信息并结束程序。
2. 系数设置:定义一个数组存储从身份证号第一位到第十七位对应的系数,即 7、9 、10、 5、 8、 4 、2 、1、 6 、3、 7、 9 、10 、5 、8 、4、 2 。
3. 计算乘积和:遍历输入的 17 位数字字符串,将每个字符转换为数字后与对应的系数相乘,并将结果累加起来,得到乘积和。
4. 计算余数:用上述得到的乘积和除以 11,计算出余数。
5. 确定校验码:定义一个数组存储余数 0 - 10 分别对应的校验码 1、0、X、9、8、7、6、5、4、3、2 。根据计算得到的余数,从该数组中获取对应的校验码。
6. 输出结果:将输入的 17 位字符串与计算得到的校验码拼接,输出完整的 18 位身份证号。

算法分析
1. 时间复杂度:主要操作是遍历输入的 17 位数字字符串进行乘法和累加操作,以及计算余数和获取校验码等简单操作。由于输入固定为 17 位,遍历操作的时间复杂度为常数级,整体时间复杂度为O(1)。
2. 空间复杂度:程序中使用了两个数组来存储系数和校验码,以及一些变量来存储中间计算结果和输入字符串等。数组大小固定,额外使用的空间不会随着输入规模的变化而变化,因此空间复杂度也为O(1)。
3. 正确性:严格按照身份证号校验位的计算标准 ISO 7064:1983 标准的 MOD 11-2 校验算法实现,只要输入符合要求(17 位数字),就能正确计算出对应的校验位,保证了结果的正确性。

总结
本题主要围绕身份证号校验位的计算算法展开,通过对输入的处理、系数的应用、乘积和与余数的计算以及校验码的确定等步骤,实现了生成完整 18 位身份证号的功能。程序在设计上考虑了输入格式的检查,具有一定的健壮性。从算法角度看,时间和空间复杂度都较低,效率较高且能保证结果的准确性。但在实际应用中,还可进一步增强输入验证的全面性,如检查输入字符是否全为数字等,以提高程序的稳定性和可靠性。
题目集5-2:

定义一个类用于计算根

设计思路
1. 输入处理:
使用  Scanner  类从控制台读取用户输入的三个双精度浮点数  a 、 b 、 c ,分别作为二次方程  ax² + bx + c = 0  的系数。若  a  的值为 0,因为此时方程不是二次方程,属于格式错误,输出 "Wrong Format" 并终止程序。
2. 类的定义:
定义了  QuadraticEquation  类来表示二次方程。该类包含三个私有成员变量  a 、 b 、 c  用于存储方程的系数。

  • 提供了两个构造函数:一个无参构造函数,将  a 、 b 、 c  初始化为 0;另一个有参构造函数,用于初始化方程的系数。
  • 为每个成员变量提供了相应的  getter  和  setter  方法,方便访问和修改成员变量的值。
  • 实现了  getDiscriminant  方法用于计算判别式  b² - 4ac 。
  • 实现了  getRoot1  和  getRoot2  方法分别计算方程的两个根。
    3. 方程求解与输出:
    创建  QuadraticEquation  类的对象  equation ,传入读取的系数。计算判别式  discriminant  后,根据判别式的值进行不同的输出:
  • 若  discriminant < 0 ,说明方程无实根,输出 "The equation has no roots."。
  • 若  discriminant == 0 ,说明方程有一个实根,输出根的值,使用  String.format("%.2f",...)  格式化输出,保留两位小数。
  • 若  discriminant > 0 ,说明方程有两个实根,输出两个根的值,同样保留两位小数。

算法分析
1. 时间复杂度:
代码的主要操作是基本的算术运算(如乘法、加法、减法、平方根运算等)以及条件判断。这些操作的时间复杂度都是常数级别的。因此,整个程序的时间复杂度为 O(1),不随输入数据的规模变化而变化。
2. 空间复杂度:
程序中主要使用了几个基本数据类型的变量( double  类型的  a 、 b 、 c 、 discriminant  等)以及  QuadraticEquation  类的对象。这些变量和对象占用的空间都是固定的,不会随着输入数据的规模而增加。所以,空间复杂度为 O(1)。
3. 正确性:
该程序按照二次方程的求解逻辑,根据判别式的值正确地计算并输出方程的根或相应的提示信息。只要输入的系数是合理的数值,就能得到正确的结果。但对于输入的有效性检查还不够全面,例如没有检查输入是否为合法的数字格式等。

总结
这段代码实现了求解二次方程的功能,通过定义  QuadraticEquation  类封装了方程的属性和相关操作,使代码结构更加清晰和模块化。程序对判别式的不同情况进行了合理的处理,能准确输出方程的根或相应提示。然而,在输入验证方面存在一定的局限性,仅检查了  a  是否为 0,没有对输入数据的其他有效性进行检查。在实际应用中,可以进一步完善输入验证逻辑,提高程序的健壮性和可靠性。
题目集5-3

设计分析
1. 输入处理:

  • 使用  Scanner  类从控制台读取用户输入的字符串  s ,这里使用  nextLine()  方法可以读取包含空格的完整字符串。
  • 首先检查输入字符串  s  的长度是否为 4。如果长度不为 4,直接输出该字符串不属于验证码的提示信息并结束程序,这是对验证码基本格式的初步检查。
    2. 字符验证:
  • 定义一个计数器变量  m  并初始化为 0,用于记录符合要求的字符个数。
  • 通过一个  for  循环遍历输入字符串的每个字符(索引从 0 到 3)。
  • 在循环内部,使用条件判断  !((s.charAt(i)>='a'&&s.charAt(i)<='z')||(s.charAt(i)>='A'&&s.charAt(i)<='Z')||(s.charAt(i)>='0'&&s.charAt(i)<='9'))  来检查每个字符是否既不是小写字母、大写字母,也不是数字。如果发现这样的字符,就使用  break  语句跳出循环。
  • 如果字符符合要求(是小写字母、大写字母或数字之一),则将计数器  m  的值加 1。
    3. 结果输出:
  • 循环结束后,检查计数器  m  的值是否为 4。如果  m  等于 4,说明字符串的 4 个字符都符合要求,输出该字符串属于验证码的提示信息。
  • 如果  m  不等于 4,说明字符串中存在不符合要求的字符,输出该字符串不属于验证码的提示信息。

算法分析
1. 时间复杂度:

  • 程序主要的操作是遍历输入字符串的字符,循环次数固定为 4 次(因为验证码长度固定为 4)。每次循环中的操作(字符判断和计数器更新)都是常数时间操作。因此,整体的时间复杂度为 O(1),与输入数据的规模无关(这里输入数据规模固定为 4 个字符)。
    2. 空间复杂度:
  • 程序中使用了一些基本数据类型的变量(如  m  和循环变量  i )以及一个字符串变量  s 。这些变量占用的空间都是固定的,不随输入数据的变化而变化。因此,空间复杂度为 O(1)。
    3. 正确性:
  • 该程序能够正确判断输入的 4 个字符的字符串是否仅由字母(大小写)和数字组成。如果输入的字符串长度不是 4 或者包含其他字符,都能正确地输出不属于验证码的提示信息;如果字符串符合要求,则输出属于验证码的提示信息。

总结
这段代码实现了一个简单的验证码验证功能,通过对输入字符串的长度和字符组成进行检查来判断其是否为有效的验证码。代码逻辑清晰,结构简单,对于固定长度为 4 且字符限定为字母和数字的验证码验证需求能够很好地满足。但该程序的局限性在于只能验证长度为 4 的验证码,如果需要验证不同长度的验证码,需要对代码进行修改。此外,在输入处理方面,没有对异常输入(如非字符串输入等)进行更完善的处理,可进一步增强程序的健壮性。
题目集5-4

设计分析
1. 输入处理:

  • 使用  Scanner  类从控制台读取用户输入的字符串  s ,通过  nextLine()  方法获取用户输入的内容,该方法可以读取包含空格的完整字符串。
    2. 初步格式验证:
  • 检查输入字符串  s  的长度是否在 5 到 15 个字符之间(包含 5 和 15),并且检查字符串的第一个字符是否为  '0' 。如果不满足这些条件(即长度小于 5、大于 15 或者第一个字符是  '0' ),则认为输入的 QQ 号格式不正确,输出 “你输入的 QQ 号验证失败” 的提示信息,并使用  return  语句结束程序。
    3. 字符类型验证:
  • 定义一个计数器变量  m (虽然在后续代码中  m  的值没有实际作用,只是声明了但未使用)。
  • 通过一个  for  循环遍历输入字符串  s  的每个字符。在循环内部,使用条件判断  !((s.charAt(i)>='0'&&s.charAt(i)<='9'))  来检查每个字符是否不是数字。如果发现有字符不是数字,则认为输入的 QQ 号格式不正确,输出 “你输入的 QQ 号验证失败” 的提示信息,并使用  return  语句结束程序。
    4. 验证成功输出:
  • 如果程序能够顺利通过前面的长度检查和字符类型检查,说明输入的字符串符合 QQ 号的基本格式要求,输出 “你输入的 QQ 号验证成功” 的提示信息。

算法分析
1. 时间复杂度:

  • 程序主要有两个关键操作。第一个是检查字符串长度和首字符,这是常数时间操作,时间复杂度为 O(1)。第二个是遍历字符串检查每个字符是否为数字,循环次数取决于字符串的长度,最多循环 15 次(因为字符串长度最大为 15)。每次循环中的字符判断操作是常数时间的。所以整体时间复杂度为 O(n),其中 n 是输入字符串的长度,由于 n 的最大值固定为 15,也可以近似认为是常数时间复杂度 O(1)。
    2. 空间复杂度:
  • 程序中使用了一些基本数据类型的变量(如  m  和循环变量  i )以及一个字符串变量  s 。这些变量占用的空间都是固定的,不随输入数据的变化而变化。因此,空间复杂度为 O(1)。
    3. 正确性:
  • 该程序能够正确验证输入的字符串是否符合 QQ 号的基本格式要求(长度在 5 到 15 之间,首字符不为  '0' ,且全部由数字组成)。如果不符合这些条件,能够正确输出验证失败的提示信息;如果符合条件,则输出验证成功的提示信息。

总结
这段代码实现了一个简单的 QQ 号格式验证功能,通过对输入字符串的长度、首字符以及字符类型进行检查来判断其是否为有效的 QQ 号格式。代码逻辑较为清晰,结构简单易懂。但该程序存在一些局限性,例如没有对更复杂的情况进行处理,如 QQ 号可能存在的其他特殊规则(实际上真实的 QQ 号规则更复杂),并且在输入处理方面,没有对异常输入(如非字符串输入等)进行更完善的处理。可以进一步增强程序的健壮性和功能完整性。
题目集6-1


设计分析
1. 输入处理:

  • 使用  Scanner  类从控制台读取用户输入。依次读取四个  double  类型的值,分别表示两个点的  x  和  y  坐标( x1 ,  y1 ,  x2 ,  y2 ),然后使用  nextLine()  读取一行字符串作为直线的颜色信息。
  • 对输入的坐标值进行范围检查,判断  x1 ,  x2 ,  y1 ,  y2  是否在  0  到  200 (不包括  0 ,包括  200 )的范围内。如果有任何一个坐标值不在此范围内,则输出 “Wrong Format” 并结束程序。
    2. 类的设计:
  • Point  类:
  • 包含私有成员变量  x  和  y  用于存储点的坐标。
  • 提供了两个构造函数,一个无参构造函数将坐标初始化为  (0, 0) ,另一个有参构造函数用于根据传入的坐标值初始化点。
  • 有  getX()  和  getY()  方法获取坐标值, setX()  和  setY()  方法设置坐标值。
  • 定义了  display1()  和  display2()  方法分别用于输出直线起点和终点的坐标,格式化输出保留两位小数。
  • Line  类:
  • 包含私有成员变量  point1  和  point2  表示直线的两个端点, color  表示直线的颜色。
  • 提供了两个构造函数,一个无参构造函数,一个有参构造函数用于初始化直线的两个端点和颜色。
  • 有  getPoint1()  和  getPoint2()  方法获取端点对象, setPoint1()  和  setPoint2()  方法设置端点对象, getColor()  方法获取颜色, setColor()  方法设置颜色(但此方法中  this.color = color;  语句无实际作用,因为没有传入新的颜色值)。
  • 实现了  getDistance()  方法,根据两点间距离公式计算直线的长度。
  • 定义了  display()  方法,调用  getDistance()  方法获取直线长度并格式化输出保留两位小数。
    3. 对象创建与操作:
  • 根据输入的坐标值创建两个  Point  对象  point1  和  point2 ,再使用这两个点对象和颜色信息创建  Line  对象  line 。
  • 输出直线的颜色,然后分别调用两个点对象的  display1()  和  display2()  方法输出起点和终点坐标,最后调用直线对象的  display()  方法输出直线长度。

算法分析
1. 时间复杂度:

  • 输入部分读取数据和检查坐标范围,都是常数时间操作,时间复杂度为 O(1)。
  • 对象创建和方法调用部分,创建对象的操作时间复杂度为常数级, getDistance()  方法中的计算操作也是常数时间(主要是基本算术运算和平方根运算), display()  方法调用  getDistance()  方法也是常数时间。所以整体时间复杂度为 O(1),不随输入数据规模变化而变化。
    2. 空间复杂度:
  • 程序中使用了一些基本数据类型的变量(如  x1 ,  y1 ,  x2 ,  y2  等), Scanner  对象,以及  Point  和  Line  类的对象。这些变量和对象占用的空间都是固定的,不随输入数据的变化而变化。因此,空间复杂度为 O(1)。
    3. 正确性:
  • 该程序能够正确处理输入数据的有效性检查,根据输入创建相应的点和直线对象,并正确计算直线的长度和输出相关信息。只要输入的数据符合格式要求,就能得到正确的结果。但在  Line  类的  setColor()  方法存在逻辑上的小瑕疵,没有实际起到设置颜色的作用。

总结
这段代码实现了一个简单的图形相关的程序,通过输入点的坐标和直线颜色信息,创建点和直线对象,并输出直线的颜色、起点和终点坐标以及直线长度。代码结构清晰,通过类的设计实现了一定的封装,将点和直线的属性和操作进行了模块化处理。但在代码的健壮性方面,还可以进一步完善输入验证(如输入非数字等异常情况),并且修复  Line  类中  setColor()  方法的逻辑问题。同时,代码的扩展性也可以考虑,例如添加更多图形相关的操作和属性。
题目集6-2


设计分析
1. 类的设计:

  • Dial  类:
  • 虽然未展示完整的  Dial  类代码,但从现有方法  upPos  和  downPos  可知,它有一个私有成员变量  scale  用于表示刻度。
  • upPos  方法用于在当前刻度  scale  小于  5  时,将刻度值增加  1 。
  • downPos  方法用于在当前刻度  scale  大于  1  时,将刻度值减少  1 。
  • Brush  类:
  • 包含私有成员变量  speed  用于表示画笔的速度。
  • 提供了两个构造函数,一个无参构造函数,一个有参构造函数用于初始化画笔的速度。
  • 有  getSpeed  方法获取画笔速度, setSpeed  方法设置画笔速度。
  • Agent  类:
  • 包含私有成员变量  lever (类型为  Lever ,未展示完整代码)、 dial (类型为  Dial )和  brush (类型为  Brush ),用于组合其他类的对象。
  • 提供了带参数的构造函数,用于初始化  lever 、 dial  和  brush  这三个成员变量。
  • 有对应的  get  和  set  方法来获取和设置  lever 、 dial  和  brush  对象( setDial  和  setBrush  方法中没有实际设置新值的逻辑,只是将当前对象赋值给自己,可能是代码编写的失误)。
  • dealSpeed  方法根据  lever  的档位( getGear  方法返回值)和  dial  的刻度( getScale  方法返回值)来计算画笔的速度,并通过  brush  的  setSpeed  方法设置画笔速度。具体逻辑为:当  lever  档位为  1  时速度为  0 ;档位为  2  时,根据  dial  的不同刻度设置不同速度;档位为  3  时速度为  30 ;档位为  4  时速度为  60 。
  • show  方法用于输出画笔的当前速度。
    2. 类之间的关系:
  • Agent  类与  Lever 、 Dial  和  Brush  类之间是组合关系, Agent  类通过持有这三个类的对象来实现对它们的操作和管理,以完成计算画笔速度等功能。

算法分析
1. 时间复杂度:

  • Dial  类的  upPos  和  downPos  方法,以及  Brush  类的  getSpeed  和  setSpeed  方法都是基本的赋值和比较操作,时间复杂度为 O(1)。
  • Agent  类的  dealSpeed  方法中,主要操作是根据不同条件进行赋值,条件判断和赋值操作都是常数时间的,所以  dealSpeed  方法的时间复杂度也为 O(1)。
  • show  方法只是简单地获取并输出画笔速度,时间复杂度同样为 O(1)。因此,整体代码的时间复杂度为 O(1),不随数据规模的变化而变化。
    2. 空间复杂度:
  • 程序中使用的变量主要是基本数据类型(如  int )和对象引用(如  lever 、 dial 、 brush ),这些变量占用的空间都是固定的,不随输入数据或其他因素的变化而变化。所以,空间复杂度为 O(1)。
    3. 正确性:
  • 在当前代码逻辑下,如果  Lever  类的  getGear  方法和  Dial  类的  getScale  方法能正确返回相应的值, Agent  类的  dealSpeed  方法就能按照预设的规则正确计算画笔速度并设置。但  setDial  和  setBrush  方法存在逻辑问题,可能会影响后续对这两个对象的正确设置和使用。

总结
这段代码通过定义  Dial 、 Brush  和  Agent  类,实现了一个模拟某种设备(可能与速度调节相关)的简单程序结构。类之间通过组合关系进行协作,以完成速度计算和设置等功能。代码结构相对清晰,通过封装将不同的功能模块划分到不同的类中。然而,存在一些代码逻辑上的小问题,如  setDial  和  setBrush  方法的实现错误,以及部分类(如  Lever )代码不完整可能影响整体功能的完整性和正确性。在实际应用中,需要进一步完善和测试这些代码,确保其功能的正确实现。
题目集7-1


设计分析
1. 输入处理:

  • 使用  Scanner  类从控制台读取用户输入的三个整数,分别表示  lockNum (锁的数量)、 stockNum (枪托的数量)和  barrelNum (枪管的数量)。
  • 对输入的数量进行范围检查,判断它们是否在规定的范围内( lockNum  在 1 到 70 之间, stockNum  在 1 到 80 之间, barrelNum  在 1 到 90 之间)。如果有任何一个数量不在此范围内,则输出 “Wrong Format” 并结束程序。
    2. 类的设计:
  • Barrel  类:
  • 包含私有成员变量  price  用于存储枪管的单价。
  • 提供了两个构造函数,一个无参构造函数将单价初始化为  0 ,另一个有参构造函数用于根据传入的价格值初始化单价。
  • 有  getPrice  方法获取单价, setPrice  方法设置单价。
  • Stock  类:
  • 包含私有成员变量  price  用于存储枪托的单价。
  • 提供了两个构造函数,一个无参构造函数将单价初始化为  0 ,另一个有参构造函数用于根据传入的价格值初始化单价。
  • 有  getPrice  方法获取单价, setPrice  方法设置单价。
  • Lock  类:
  • 包含私有成员变量  price  用于存储锁的单价。
  • 提供了两个构造函数,一个无参构造函数将单价初始化为  0 ,另一个有参构造函数用于根据传入的价格值初始化单价。
  • 有  getPrice  方法获取单价, setPrice  方法设置单价。
  • SalesOrder  类:
  • 包含私有成员变量  lockNum 、 stockNum  和  barrelNum  用于存储销售订单中锁、枪托和枪管的数量。
  • 提供了两个构造函数,一个无参构造函数,一个有参构造函数用于初始化订单中的数量。
  • 有对应的  get  和  set  方法来获取和设置这些数量。
  • getTotal  方法用于计算订单的总销售额,根据不同商品的单价和数量进行计算(锁单价 45,枪托单价 30,枪管单价 25)。
  • getCommission  方法根据总销售额计算销售佣金,按照不同的销售额区间采用不同的佣金比例进行计算:销售额大于 1800 时,1000 部分按 10%,800 部分按 15%,超过 1800 的部分按 20%;销售额在 1000 到 1800 之间时,1000 部分按 10%,超过 1000 的部分按 15%;销售额小于等于 1000 时,按 10%计算。
    3. 对象创建与操作:
  • 根据固定的单价创建  Barrel 、 Stock  和  Lock  对象。
  • 使用用户输入的数量创建  SalesOrder  对象。
  • 调用  SalesOrder  对象的  getTotal  方法计算总销售额,再调用  getCommission  方法计算销售佣金,并将结果格式化输出(保留两位小数)。

算法分析
1. 时间复杂度:

  • 输入部分读取数据和检查范围,都是常数时间操作,时间复杂度为 O(1)。
  • 对象创建和方法调用部分,创建对象的操作时间复杂度为常数级, getTotal  方法中的计算操作是基本的乘法和加法运算,时间复杂度为 O(1), getCommission  方法中的条件判断和计算操作也是常数时间的。所以整体时间复杂度为 O(1),不随输入数据规模变化而变化(这里数据规模指商品数量,数量范围固定)。
    2. 空间复杂度:
  • 程序中使用了一些基本数据类型的变量(如  lockNum 、 stockNum 、 barrelNum  等), Scanner  对象,以及  Barrel 、 Stock 、 Lock  和  SalesOrder  类的对象。这些变量和对象占用的空间都是固定的,不随输入数据的变化而变化。因此,空间复杂度为 O(1)。
    3. 正确性:
  • 该程序能够正确处理输入数据的有效性检查,根据输入创建相应的对象,并按照预设的逻辑正确计算总销售额和销售佣金。只要输入的数据符合格式要求,就能得到正确的结果。

总结
这段代码实现了一个简单的销售订单处理程序,通过输入商品的数量,结合固定的单价,计算订单的总销售额和销售佣金。代码结构清晰,通过类的设计实现了一定的封装,将不同商品的属性和订单相关的操作进行了模块化处理。程序对输入数据进行了有效性检查,增强了程序的健壮性。然而,代码的扩展性可以进一步考虑,例如如果商品种类或价格发生变化,需要修改较多的代码;同时,在输入处理方面,还可以增加对异常输入(如非整数输入等)的处理。
题目集7-2


设计分析
1. 类的设计:

  • Rectangle  类:
  • 包含私有成员变量  width  和  length  分别表示矩形的宽和长,以及一个未展示完整代码的  Coordinate  类型的成员变量  coordinate (推测用于表示矩形的某个坐标位置)。
  • 提供了两个构造函数,一个无参构造函数,另一个有参构造函数用于根据传入的  Coordinate  对象、宽度和长度来初始化矩形。
  • 有对应的  get  和  set  方法来获取和设置  coordinate 、 length  和  width 。
  • MonteCarloSimulation  类:
  • 包含私有成员变量  rectangle (类型为  Rectangle )和  circle (类型为  Circle ,未展示完整代码),用于组合矩形和圆的对象。
  • 提供了三个构造函数,一个无参构造函数,一个接受  Rectangle  和  Circle  对象的构造函数,以及一个只接受  Rectangle  对象的构造函数。
  • 有对应的  get  和  set  方法来获取和设置  rectangle  和  circle  对象。
  • validateRectangle  方法用于验证矩形的合法性,通过比较矩形的长和宽是否相等(使用  Double.compare  方法)以及长和宽是否大于等于 0 来判断。如果长小于 0、宽小于 0 或者长不等于宽,则返回  false ,否则返回  true 。
  • setCircle  方法根据矩形的坐标和边长来设置圆的属性。计算出圆心的坐标(矩形中心),并使用该坐标和矩形边长的一半作为半径来创建一个新的  Circle  对象并赋值给  circle  成员变量。
  • simulation  方法实现了蒙特卡罗模拟算法。通过生成  n  个在矩形范围内的随机点(通过  random.nextDouble()  生成随机坐标),判断这些点是否在圆内(通过  getDistance  方法计算点到圆心的距离并与圆的半径比较),统计在圆内的点的数量  insideCircle ,最后根据公式  4.0 * insideCircle / n  计算出一个近似值(可能与圆的面积和矩形面积的比例相关)。
  • getDistance  方法根据两点的坐标计算它们之间的距离,使用勾股定理(计算横纵坐标差值的平方和的平方根)。
    2. 类之间的关系:
  • MonteCarloSimulation  类与  Rectangle  和  Circle  类之间是组合关系, MonteCarloSimulation  类通过持有这两个类的对象来实现对矩形和圆相关操作的管理和模拟计算。

算法分析
1. 时间复杂度:

  • Rectangle  类的  get  和  set  方法是基本的赋值和返回操作,时间复杂度为 O(1)。
  • MonteCarloSimulation  类的  validateRectangle  方法主要是比较和条件判断操作,时间复杂度为 O(1)。
  • setCircle  方法的操作包括获取矩形的属性和创建圆对象,时间复杂度也为 O(1)。
  • simulation  方法中有一个循环  n  次的操作,每次循环内进行随机数生成、坐标计算和距离判断等操作,这些操作的时间复杂度为常数级,所以  simulation  方法的时间复杂度为 O(n),其中  n  是模拟的次数。
  • getDistance  方法的操作是基本的算术运算,时间复杂度为 O(1)。整体来看,当进行模拟操作时,程序的时间复杂度主要由  simulation  方法决定,为 O(n)。
    2. 空间复杂度:
  • 程序中使用的变量主要是基本数据类型(如  double )、对象引用(如  rectangle 、 circle )以及在方法中创建的临时对象(如  Coordinate  对象)。这些变量和对象占用的空间都是固定的,不随输入数据或模拟次数  n  的变化而变化(除了在  simulation  方法中每次循环创建的  Coordinate  对象,但它们会被及时回收)。所以,空间复杂度为 O(1)。
    3. 正确性:
  • 在当前代码逻辑下,如果  Rectangle 、 Circle  和  Coordinate  类的方法能正确实现其功能, MonteCarloSimulation  类的方法就能按照预设的逻辑进行矩形验证、圆的设置和蒙特卡罗模拟计算。但由于部分类(如  Circle  和  Coordinate )代码不完整,可能会影响整体功能的正确性和完整性。

总结
这段代码通过定义  Rectangle  和  MonteCarloSimulation  类,实现了一个与矩形、圆相关的模拟计算功能(蒙特卡罗模拟)。代码结构相对清晰,通过类的封装和组合关系,将不同的功能模块划分到不同的类中。然而,存在一些不足之处,如部分类代码不完整,可能会影响程序的正确性;在代码的健壮性方面,对于一些边界情况(如随机数生成的特殊情况等)没有进行更完善的处理。在实际应用中,需要进一步完善这些类的代码,进行充分的测试,以确保程序的稳定性和准确性。
电梯
最后三道电梯题目难度较大,目前还是没有征服,给出的样例只能成功输出一个,但是通过此次电梯题目,我掌握了队列的用法,Treemap的用法,以及对面向对象更加熟练







以上是我的电梯代码
(3)采坑心得:
心路历程回顾
在刚开始接触电梯题目时,我满怀信心,觉得凭借之前的知识积累能够顺利完成。但随着深入研究题目,发现实际难度远超想象,信心开始受挫。在不断尝试编写代码,却频繁遭遇错误和失败时,内心充满焦虑与沮丧,甚至开始怀疑自己的编程能力。但在老师和同学的鼓励下,我尝试重新振作,不断查阅资料、请教他人,努力寻找解决问题的方法,虽最终未能完成电梯程序,但在这个过程中,我逐渐学会正视自己的不足,心态也从最初的焦虑变得更加沉稳,明白学习是一个长期积累的过程,遇到困难是正常的,关键是如何从失败中吸取教训。
未完成电梯程序原因深度剖析
1.分析与设计能力薄弱:面对电梯调度这类复杂问题,缺乏系统分析问题的方法。未能清晰界定电梯、乘客等对象的属性和行为,以及它们之间的交互关系,导致类设计混乱,代码结构松散。例如,在设计Elevator类时,不清楚该将哪些操作归为电梯的核心职责,哪些应与乘客类协同完成,使得代码逻辑混乱,难以维护和扩展。
2.实践经验匮乏:日常编程练习局限于简单示例,缺乏对实际复杂项目的实践。面对电梯程序这种综合性较强的任务,缺乏应对经验,不知如何从整体架构出发,逐步细化功能模块,在遇到问题时,也没有有效的调试和解决问题的方法,只能在错误的道路上越走越远。
(4)改进建议:
可以多分几个文件,提高可读性
(5)总结:
通过对本阶段三次题目集的深入学习和实践,我收获颇丰。在知识层面,不仅巩固和深化了面向对象编程的基本概念和技巧,还学习了算法优化、多线程编程等高级知识。在编程能力方面,通过不断地解决各种复杂的问题,提高了自己分析问题、设计解决方案以及编写高质量代码的能力。同时,在遇到问题和解决问题的过程中,培养了自己的调试能力和耐心。
然而,我也意识到自己在某些方面还存在不足,需要进一步学习和研究。例如,在算法设计方面,虽然能够实现基本的功能,但对于一些复杂的算法优化问题,还缺乏深入的理解和实践经验。在多线程编程中,对于线程安全和并发控制的掌握还不够熟练,需要进一步学习相关的理论知识,并通过更多的实践项目来提升自己的能力。
对于教师而言,建议在教学过程中,可以增加一些实际项目案例的讲解,让我们更好地理解所学知识在实际应用中的场景和作用。在课程设置方面,可以适当增加一些实验课时,让我们有更多的时间进行实践操作,巩固所学知识。对于作业和实验的布置,可以更加注重题目之间的关联性和递进性,让我们在完成作业的过程中,逐步构建起完整的知识体系。在课上及课下组织方式上,可以多开展一些小组讨论和项目合作活动,培养我们的团队协作能力和沟通能力。
总之,通过这三次题目集的学习,我在编程的道路上迈出了坚实的一步,但也明确了自己未来的努力方向。我相信,在教师的指导和自己的不断努力下,能够不断提升自己的编程水平,为今后的学习和工作打下坚实的基础。

posted @ 2025-04-14 17:58  24201725-孙思成  阅读(51)  评论(0)    收藏  举报