每日一题——Python实现PAT乙级1032 挖掘机技术哪家强(举一反三+思想解读+逐步优化)


一个认为一切根源都是“自己不够强”的INTJ

个人主页:用哲学编程-CSDN博客
专栏:每日一题——举一反三
Python编程学习
Python内置函数

Python-3.12.0文档解读

目录

我的写法

专业点评

时间复杂度

空间复杂度

总结

我要更强

时间复杂度和空间复杂度分析

总结

哲学和编程思想

1. 简洁性 (Keep it Simple, Stupid - KISS)

2. 可读性优先

3. 鲁棒性 (Robustness)

4. 优化

5. 预防性编程

6. 迭代改进

举一反三

1. 保持代码简洁

2. 提高可读性

3. 增强鲁棒性

4. 持续优化

5. 预防性编程

6. 迭代改进

7. 重构



题目链接


我的写法

N=int(input())  # 用户输入行数N
schools_scores={}  # 初始化学校得分字典
school,score=0,0  # 初始化学校编号和得分变量
for i in range(N):  # 对每一行输入进行循环
    school,score=map(int,input().split())  # 读取每行的学校编号和得分
    if school in schools_scores:  # 如果学校已存在于字典中
        schools_scores[school]+=score  # 累加该学校的得分
    else:  # 如果学校不在字典中
        schools_scores[school]=score  # 在字典中为该学校创建得分记录
# 以下两行均可,用于初始化最好学校和最高分数
# best_school,max_score=school,score
best_school,max_score=0,-1  # 初始化最好学校编号和最高得分
# 初始值不能为0,0 否则不通过
# 说明,找最值初始化有两种方式
# 1.超出值域的值
# 2.其中一个元素的值
for k,v in schools_scores.items():  # 遍历学校及其得分
    if v>=max_score:  # 如果找到一个更高的得分
        max_score=v  # 更新最高得分
        best_school=k  # 更新得分最高的学校编号

print(best_school,max_score,sep=' ')  # 输出得分最高的学校编号和得分

这段代码基本上实现了根据输入的学校编号和得分,计算并输出得分最高的学校编号及其得分。现在,让我们从专业角度进行点评,并分析其时间复杂度和空间复杂度。

专业点评

  1. 逻辑正确性:代码逻辑上是正确的,能够处理包含多个学校得分的情况,并正确地找到并输出得分最高的学校编号及其得分。
  2. 可读性:代码简洁,易于理解。通过适当的变量命名和保持结构的简单性,提高了代码的可读性。但是,对于初始值的选择和循环逻辑部分,更多的注释可能会有助于解释为什么采用特定的初始化方法(尤其是 best_school,max_score=0,-1)。
  3. 健売性:代码对于正整数分数的场景表现良好,但如果考虑到可能存在的负分数输入,初始化 max_score 为 -1 可能不是最佳选择。理想情况下,max_score 应该初始化为 float('-inf'),即负无穷大,以确保即便是负分数也能被正确处理。

时间复杂度

  1. 输入处理循环:时间复杂度为 O(N),其中 N 是输入的行数(即学校编号和得分的对数)。每次迭代仅包含常数时间操作(字典访问和更新)。
  2. 查找最高得分循环:时间复杂度也是 O(N),其中 N 是字典 schools_scores 中的项数。在最坏的情况下,这个数字可能与输入的行数相同,尤其是当每行的学校编号都不相同时。

综上所述,整体时间复杂度为 O(N)。

空间复杂度

  1. 字典存储:空间复杂度为 O(N),用于存储每个学校的得分。在最坏的情况下,如果每行输入的学校编号都不相同,那么需要存储 N 个项。
  2. 变量存储:除字典外,使用了常数个辅助变量,如 school, score, best_school, max_score 等,这些对总空间复杂度的影响可以忽略不计。

因此,整体空间复杂度为 O(N)。

总结

这段代码是处理给定问题的有效方式,具有很好的时间和空间效率(均为 O(N))。对初始值选择的小小改进(使用负无穷大来初始化 max_score)可以使它更加健壮,尤其是在处理可能包含负值得分的输入时。


我要更强

为了优化时间复杂度和空间复杂度,我们可以考虑以下几个方面:

  1. 空间优化:如果输入的学校编号是连续的,我们可以使用数组代替字典来存储得分,这样可以节省空间。
  2. 时间优化:在更新最高得分时,我们可以使用更高效的数据结构,如堆(heap),来实时跟踪最高得分。

然而,由于输入的学校编号通常不是连续的,且我们无法预知其范围,因此使用数组的空间优化方法不适用。同样,由于我们需要实时跟踪最高得分,使用堆等数据结构可能会增加额外的复杂性,而不是简化问题。

因此,最实际的优化方法可能是在代码结构和逻辑上进行微调,以确保代码的效率和可读性。以下是优化后的代码:

# 读取输入的行数N
N = int(input())

# 初始化字典,用于存储每个学校的总分
schools_scores = {}

# 读取每行输入的学校编号和得分,并更新字典
for _ in range(N):
    school, score = map(int, input().split())
    if school in schools_scores:
        schools_scores[school] += score
    else:
        schools_scores[school] = score

# 初始化最高得分为负无穷大,确保可以正确处理所有可能的得分
max_score = float('-inf')
best_school = None

# 遍历字典,找到得分最高的学校
for school, score in schools_scores.items():
    if score > max_score:
        max_score = score
        best_school = school

# 输出得分最高的学校编号和得分
print(best_school, max_score)

时间复杂度和空间复杂度分析

  • 时间复杂度:仍然是 O(N),其中 N 是输入的行数。这是因为我们仍然需要遍历所有输入来构建字典,并且需要遍历字典来找到最高得分。
  • 空间复杂度:仍然是 O(N),因为我们需要存储每个学校的得分。在最坏的情况下,如果每个学校的编号都不同,我们将需要存储 N 个项。

总结

这段代码在逻辑上与原始代码相同,但在初始化最高得分时使用了更合适的值(负无穷大),以确保能够正确处理所有可能的得分。此外,代码结构更加清晰,有助于提高可读性。尽管时间复杂度和空间复杂度没有实质性的改变,但这种微调有助于确保代码的健壮性和效率。


哲学和编程思想

在对代码进行优化时,采用了几种编程和设计哲学,这些哲学帮助提升代码的效率、可读性和健壮性。具体来说,以下是一些显著的思想:

1. 简洁性 (Keep it Simple, Stupid - KISS)

优化后的代码遵循简洁性原则,尽量减少复杂度。通过维持一个简单的逻辑流程来累加每个学校的得分,并在遍历完成后确定最高分,这种方法避免了使用复杂数据结构或算法,从而保持了代码的简单易懂。

2. 可读性优先

代码的可读性是一个重要考虑因素,尤其是在团队合作和代码维护时。通过使用清晰的变量命名(如 schools_scores)和保持逻辑结构的直观性,代码易于被他人理解和审查。优化后的代码通过简化逻辑和增加注释,进一步提升了可读性。

3. 鲁棒性 (Robustness)

通过初始化 max_score 为负无穷大,代码变得更加健壮,能够正确处理所有可能的得分(包括负分)。这体现了在设计时考虑极端和边界情况的重要性,以确保代码在各种输入下都能正常工作。

4. 优化

尽管在这个例子中时间复杂度和空间复杂度没有显著改变(依然是 O(N)),但是通过逻辑上的优化(如更合理的初始化方式),代码更加健壮且易于维护。这种优化思想体现了在不牺牲代码可读性和简洁性的前提下,通过微小的调整提升代码整体质量的努力。

5. 预防性编程

代码通过对最高得分 max_score 使用负无穷大的初始化,体现了预防性编程的思想。这种方法通过提前考虑到潜在的问题(例如输入中可能包含的负分数)并采取措施来避免这些问题,减少了未来可能需要的修复和调试工作。

6. 迭代改进

优化过程体现了迭代改进的思想。即代码的初版可能已经足够好,但通过不断的评估和小的改进,可以使其更接近完美。这种逐步优化的方法,是软件开发中常见的实践。

通过这种方式,优化后的代码在保持其原有目的的同时,变得更加健壮、可读和简洁。这些编程和设计哲学不仅适用于当前的场景,也是广泛应用于软件开发和架构设计中的通用原则。


举一反三

根据上述提到的哲学和编程思想,以下是一些实用的技巧,可以帮助在编程时举一反三,提高代码质量和效率:

1. 保持代码简洁

  • 避免过度设计:不要为可能不会发生的问题预先编写复杂的解决方案。保持代码简单,只解决当前已知的问题。
  • 单一职责原则:确保每个函数或类只做一件事。这有助于简化代码并使其更易于理解和维护。

2. 提高可读性

  • 良好的命名:使用描述性的变量和函数名,使代码自解释。
  • 注释和文档:在关键部分添加注释,解释代码的意图和逻辑。定期更新文档,确保其与代码同步。
  • 代码格式化:遵循一致的代码风格和格式,使用工具自动格式化代码。

3. 增强鲁棒性

  • 边界条件处理:在编写代码时考虑所有可能的输入情况,包括边界条件和异常情况。
  • 错误处理:合理使用异常处理机制,确保程序在遇到错误时能够优雅地处理,而不是崩溃。

4. 持续优化

  • 代码审查:定期进行代码审查,从同事那里获得反馈,发现潜在的改进点。
  • 性能分析:使用性能分析工具来识别瓶颈,并针对性地进行优化。

5. 预防性编程

  • 防御性编程:在代码中加入检查,确保输入和状态的有效性,防止潜在的错误。
  • 单元测试:编写单元测试来验证代码的正确性,确保代码在修改后仍能按预期工作。

6. 迭代改进

  • 小步快跑:采用敏捷开发方法,通过频繁的迭代来逐步完善产品。
  • 反馈循环:建立快速反馈机制,无论是通过自动化测试还是用户反馈,都能帮助你及时调整方向。

7. 重构

  • 定期重构:随着项目的发展,定期重构代码以消除技术债务,提高代码质量。
  • 保持代码整洁:遵循《代码整洁之道》等书籍中的原则,持续改进代码结构。

通过应用这些技巧,可以在编程时更加高效和有目的性,同时确保代码的质量和可维护性。记住,编程不仅仅是实现功能,更是一种艺术和科学的结合,需要不断学习和实践。


感谢阅读。

  • 28
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

用哲学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值