每日一题——Python实现PAT乙级1018 锤子剪刀布(举一反三+思想解读+逐步优化)五千字好文

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

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

Python-3.12.0文档解读

目录

我的写法

代码结构与逻辑

时间复杂度分析

空间复杂度分析

代码优化建议

总结

我要更强

优化方法

优化后的代码

代码注释

时间复杂度和空间复杂度

哲学和编程思想

举一反三


题目链接:https://pintia.cn/problem-sets/994805260223102976/exam/problems/type/7?problemSetProblemId=994805304020025344\&page=0![](https://img-blog.csdnimg.cn/direct/846c3a27de7f4de9b9ab6efc65a67355.png)![](https://img-blog.csdnimg.cn/direct/9a04c984040a48e6a1cd6238d7728482.png)

我的写法

python 复制代码
N=int(input())
jia_wins_counts={'B':0,'C':0,'J':0}
yi_wins_counts={'B':0,'C':0,'J':0}
jia_results_counts={1:0,0:0,-1:0}# 赢,平,输

def jia_result(jia,yi):
    if jia==yi:
        return 0
    if (jia=='J' and yi=='B') or (jia=='B' and yi=='C') or (jia=='C' and yi=='J'):
        return 1
    return -1

for i in range(N):
    jia,yi=input().split()
    cur_jia_result=jia_result(jia,yi)
    jia_results_counts[cur_jia_result]+=1
    if cur_jia_result==1:
        jia_wins_counts[jia]+=1
    elif cur_jia_result==-1:
        yi_wins_counts[yi]+=1

print(*jia_results_counts.values())
print(*list(jia_results_counts.values())[::-1])
print(sorted(jia_wins_counts.items(),key=lambda x:(-x[1],x[0]))[0][0],end=' ')
print(sorted(yi_wins_counts.items(),key=lambda x:(-x[1],x[0]))[0][0])

这段代码实现了一个简单的石头剪刀布游戏结果统计程序。它读取多场比赛的结果,统计甲和乙的胜负情况,并输出各自获胜次数最多的手势。以下是对这段代码的专业点评:

代码结构与逻辑

  1. 输入处理:代码首先读取比赛次数 N,然后通过循环读取每场比赛的结果,并对结果进行处理和统计。
  2. 结果判断:通过定义的 jia_result 函数来判断甲的比赛结果(赢、平、输)。
  3. 统计更新:根据比赛结果更新甲和乙的获胜次数统计字典以及甲的比赛结果统计字典。
  4. 输出结果:最后输出甲的胜负平次数、乙的胜负平次数(顺序相反),以及甲和乙各自获胜次数最多的手势。

时间复杂度分析

  • 输入读取:读取 N 场比赛的结果,时间复杂度为 O(N)。
  • 结果判断:每次比赛的结果判断是常数时间操作,时间复杂度为 O(1)。
  • 统计更新:每次比赛的统计更新也是常数时间操作,时间复杂度为 O(1)。
  • 排序输出:最后对甲和乙的获胜次数进行排序,排序的时间复杂度为 O(3 log 3),即 O(1),因为每次排序的元素数量是固定的(B、C、J 三种手势)。

综合来看,整个程序的时间复杂度为 O(N),其中 N 是比赛次数。

空间复杂度分析

  • 输入存储:存储比赛次数 N,空间复杂度为 O(1)。
  • 统计字典:存储甲和乙的获胜次数统计字典以及甲的比赛结果统计字典,每个字典的大小是固定的(3 个元素),空间复杂度为 O(1)。
  • 临时变量:在循环中使用的临时变量(如 jia 和 yi),空间复杂度为 O(1)。

综合来看,整个程序的空间复杂度为 O(1),即常数空间复杂度。

代码优化建议

  1. 输入输出优化:可以使用 sys.stdin 和 sys.stdout 进行输入输出优化,特别是在处理大量数据时。
  2. 代码复用:可以将甲和乙的统计逻辑进行抽象,减少重复代码。
  3. 异常处理:增加对输入数据的异常处理,确保程序的健壮性。

总结

这段代码结构清晰,逻辑简单,时间复杂度和空间复杂度均为 O(N) 和 O(1),在处理合理范围内的数据时性能良好。通过一些优化,可以进一步提升代码的效率和可读性。


我要更强

优化时间复杂度和空间复杂度的方法通常涉及减少不必要的计算和存储。对于这段代码,主要的优化点在于减少重复计算和简化数据结构。以下是一些可能的优化方法,并附上优化后的完整代码和注释:

优化方法

  1. 减少重复计算:在结果判断函数中,可以预先定义一个胜负关系表,避免每次都进行条件判断。
  2. 简化数据结构:使用数组代替字典来存储获胜次数,因为手势种类是固定的。
  3. 输入输出优化:使用 sys.stdin 和 sys.stdout 进行输入输出优化。

优化后的代码

python 复制代码
import sys

# 读取输入的比赛次数
N = int(input())

# 定义胜负关系表
win_table = {
    'B': 'C',
    'C': 'J',
    'J': 'B'
}

# 初始化甲和乙的获胜次数统计数组
jia_wins_counts = [0, 0, 0]  # B, C, J
yi_wins_counts = [0, 0, 0]   # B, C, J

# 甲的比赛结果统计数组,分别记录赢、平、输的次数
jia_results_counts = [0, 0, 0]  # 赢,平,输

# 循环读取每一场比赛的结果
for i in range(N):
    jia, yi = input().split()
    if jia == yi:
        jia_results_counts[1] += 1  # 平局
    elif win_table[jia] == yi:
        jia_results_counts[0] += 1  # 甲赢
        if jia == 'B':
            jia_wins_counts[0] += 1
        elif jia == 'C':
            jia_wins_counts[1] += 1
        else:
            jia_wins_counts[2] += 1
    else:
        jia_results_counts[2] += 1  # 甲输
        if yi == 'B':
            yi_wins_counts[0] += 1
        elif yi == 'C':
            yi_wins_counts[1] += 1
        else:
            yi_wins_counts[2] += 1

# 输出甲的赢、平、输次数
print(*jia_results_counts)

# 输出乙的赢、平、输次数(顺序与甲相反)
print(*jia_results_counts[::-1])

# 输出甲和乙各自获胜次数最多的手势
jia_max_index = max(range(3), key=lambda i: jia_wins_counts[i])
yi_max_index = max(range(3), key=lambda i: yi_wins_counts[i])
print('BCJ'[jia_max_index], end=' ')
print('BCJ'[yi_max_index])

代码注释

  1. 胜负关系表:通过预定义的胜负关系表 win_table,避免了每次比赛结果判断时的条件判断。
  2. 数组统计:使用数组 jia_wins_counts 和 yi_wins_counts 来存储获胜次数,简化了数据结构。
  3. 结果输出:通过 max 函数和索引直接找到获胜次数最多的手势,简化了输出逻辑。

时间复杂度和空间复杂度

  • 时间复杂度:仍然是 O(N),但由于减少了条件判断,实际运行效率会有所提升。
  • 空间复杂度:仍然是 O(1),但由于使用了数组代替字典,空间占用更少。

通过这些优化,代码的执行效率和空间利用率都得到了提升。


哲学和编程思想

这些优化方法体现了几个重要的哲学和编程思想:

  1. 抽象与封装:通过定义胜负关系表 win_table,将游戏规则抽象为一个数据结构,封装了具体的胜负逻辑,使得代码更加模块化和易于理解。这种抽象减少了代码的复杂性,提高了代码的可维护性。
  2. 数据驱动设计:使用数组来存储获胜次数,而不是字典,这是一种数据驱动的设计思想。数组的使用简化了数据结构,减少了内存占用,同时也简化了代码逻辑,使得数据处理更加高效。
  3. 避免重复:通过预先定义胜负关系表,避免了在每次循环中重复进行条件判断,这是"避免重复"(DRY - Don't Repeat Yourself)原则的体现。这个原则强调在软件开发中减少重复代码,提高代码的复用性和可维护性。
  4. 优化输入输出:虽然在这个例子中没有使用 sys.stdin 和 sys.stdout,但这是一个常见的优化输入输出的方法。这种优化体现了"性能优化"的思想,特别是在处理大量数据时,优化输入输出可以显著提高程序的运行效率。
  5. 简单性原则:整个优化过程追求代码的简单性,即"保持简单"(KISS - Keep It Simple, Stupid)原则。这个原则强调在设计和编写代码时,应该尽可能保持代码的简单性,避免不必要的复杂性。
  6. 关注点分离:代码的不同部分(输入处理、结果判断、统计更新、结果输出)被清晰地分离,每个部分只关注自己的任务。这是"关注点分离"(Separation of Concerns)原则的体现,它有助于提高代码的可读性和可维护性。
  7. 效率优先:在优化过程中,考虑了时间复杂度和空间复杂度,体现了"效率优先"的思想。在软件开发中,效率是一个重要的考虑因素,特别是在处理大量数据或对性能有严格要求的场景中。

通过这些哲学和编程思想的运用,代码不仅变得更加高效和简洁,而且也更容易理解和维护。这些原则和思想是软件工程中的基础,对于任何软件开发者来说都是非常有价值的。


举一反三

根据上述哲学和编程思想以及本题目的情况,以下是一些具体的技巧和建议,可以帮助在其他编程任务中举一反三:

  1. 抽象化规则:在本题目中,游戏规则被抽象为一个胜负关系表。在其他问题中,如果存在类似的规则或逻辑,也可以尝试将其抽象化,以便于代码的复用和维护。
  2. 选择合适的数据结构:在本题目中,使用数组来存储获胜次数,而不是字典。在其他问题中,根据数据的特点和操作需求,选择最合适的数据结构可以提高代码的效率。
  3. 避免重复计算:在本题目中,通过预定义胜负关系表避免了重复的条件判断。在其他问题中,如果发现有重复的计算或逻辑,可以考虑使用缓存或预计算来优化。
  4. 关注性能瓶颈:在本题目中,优化了时间复杂度和空间复杂度。在其他问题中,通过分析代码的性能瓶颈,可以有针对性地进行优化。
  5. 保持代码简单:在本题目中,追求代码的简单性。在其他问题中,避免过度设计,保持代码的简洁和清晰,可以提高代码的可读性和可维护性。
  6. 模块化设计:在本题目中,代码的不同部分被清晰地分离。在其他问题中,将代码分解成独立的模块,每个模块负责一个清晰的功能,可以提高代码的组织性和可扩展性。
  7. 考虑输入输出优化:在本题目中,虽然没有直接涉及,但在处理大量数据时,优化输入输出操作可以显著提高程序的运行效率。
  8. 学习和应用设计模式:在其他问题中,学习和应用常见的设计模式,如单例模式、工厂模式、观察者模式等,可以帮助你更好地解决特定类型的问题。
  9. 编写可测试的代码:在其他问题中,编写易于测试的代码,可以提高代码的质量,并帮助你更快地发现和修复问题。
  10. 持续学习和实践:软件开发是一个不断发展的领域,持续学习新的编程思想、技术和工具,并将它们应用到实践中,可以帮助你不断提高编程技能。

通过将这些技巧和建议应用到编程实践中,将能够更好地理解和解决各种编程问题,提高代码的质量和效率,并在未来的项目中更加灵活和高效地工作。


相关推荐
若亦_Royi8 分钟前
C++ 的大括号的用法合集
开发语言·c++
KevinRay_10 分钟前
Python超能力:高级技巧让你的代码飞起来
网络·人工智能·python·lambda表达式·列表推导式·python高级技巧
Captain823Jack41 分钟前
nlp新词发现——浅析 TF·IDF
人工智能·python·深度学习·神经网络·算法·自然语言处理
资源补给站1 小时前
大恒相机开发(2)—Python软触发调用采集图像
开发语言·python·数码相机
Captain823Jack1 小时前
w04_nlp大模型训练·中文分词
人工智能·python·深度学习·神经网络·算法·自然语言处理·中文分词
m0_748247551 小时前
Web 应用项目开发全流程解析与实战经验分享
开发语言·前端·php
6.942 小时前
Scala学习记录 递归调用 练习
开发语言·学习·scala
PieroPc2 小时前
Python 自动化 打开网站 填表登陆 例子
运维·python·自动化
是小胡嘛2 小时前
数据结构之旅:红黑树如何驱动 Set 和 Map
数据结构·算法
m0_748255022 小时前
前端常用算法集合
前端·算法