一个认为一切根源都是“自己不够强”的INTJ
个人主页:用哲学编程-CSDN博客
专栏:每日一题——举一反三
Python编程学习
Python内置函数
Python-3.12.0文档解读
目录
我的写法
时间复杂度分析
空间复杂度分析
代码优化建议
总结
我要更强
优化方法
优化后的代码
代码解释
时间复杂度分析
空间复杂度分析
总结
哲学和编程思想
抽象与封装:
效率与优化:
简洁与清晰:
不变性与可变性:
DRY原则(Don't Repeat Yourself):
KISS原则(Keep It Simple, Stupid):
YAGNI原则(You Ain't Gonna Need It):
单一职责原则(Single Responsibility Principle):
开闭原则(Open/Closed Principle):
题目链接:https://pintia.cn/problem-sets/994805260223102976/exam/problems/type/7?problemSetProblemId=994805269828059136&page=0
我的写法
import math
def is_prime(num):
if num == 2:
return True
elif num % 2 == 0 or num < 2:
return False
else:
for i in range(3, math.isqrt(num) + 1, 2):
if num % i == 0:
return False
return True
N = int(input())
tops = [int(input()) for _ in range(N)]
K = int(input())
ids = [int(input()) for _ in range(K)]
# 使用字典存储排名信息
rank_dict = {top: i + 1 for i, top in enumerate(tops)}
already_got = {top: 0 for top in tops}
if_has = {top: 1 for top in tops}
for i in range(K):
current_id = ids[i]
print(f"{str(current_id).zfill(4)}: ", end='')
if current_id not in if_has:
print("Are you kidding?")
elif already_got[current_id] == 1:
print("Checked")
elif rank_dict[current_id] == 1:
already_got[current_id] = 1
print("Mystery Award")
elif is_prime(rank_dict[current_id]):
already_got[current_id] = 1
print("Minion")
else:
already_got[current_id] = 1
print("Chocolate")
这段代码的主要功能是根据输入的排名列表和查询ID列表,输出每个查询ID对应的奖励类型。代码的逻辑如下:
- 输入处理:读取排名列表和查询ID列表。
- 字典初始化:使用字典存储排名信息和查询状态。
- 查询处理:根据查询ID输出对应的奖励类型。
时间复杂度分析
- 输入处理:读取排名列表和查询ID列表的时间复杂度是 O(N + K),其中 N 是排名列表的长度,K 是查询ID列表的长度。
- 字典初始化:使用字典推导式初始化 rank_dict、already_got 和 if_has 的时间复杂度是 O(N)。
- 查询处理:对于每个查询ID,检查其是否在 if_has 字典中,以及更新 already_got 字典的状态。这些操作的时间复杂度是 O(1)。因此,整个查询处理的时间复杂度是 O(K)。
综合来看,整个代码的时间复杂度是 O(N + K)。
空间复杂度分析
- 输入存储:排名列表和查询ID列表的空间复杂度是 O(N + K)。
- 字典存储:rank_dict、already_got 和 if_has 字典的空间复杂度是 O(N)。
综合来看,整个代码的空间复杂度是 O(N + K)。
代码优化建议
- 输入处理:确保输入的格式和类型是正确的。
- 字典初始化:使用字典推导式初始化字典时,确保键和值的类型是正确的。
- 索引处理:在检查排名时,使用字典来存储排名信息,避免使用 index 方法,提高性能。
- 输出格式:确保输出的格式是正确的。
总结
这段代码在逻辑上是正确的,时间复杂度为 O(N + K),空间复杂度为 O(N + K)。通过使用字典来存储排名信息,避免了使用 index 方法,提高了性能。整体来说,代码是高效的,并且易于理解和维护。
我要更强
优化时间复杂度和空间复杂度的方法通常包括减少不必要的计算、使用更高效的数据结构、以及避免重复计算。以下是一些可能的优化方法,并附上相应的代码和注释。
优化方法
- 避免重复计算:使用缓存或记忆化技术来存储已经计算过的结果。
- 高效数据结构:使用集合(set)来快速检查元素是否存在。
- 减少不必要的字典:合并一些字典,减少空间占用。
优化后的代码
import math
def is_prime(num):
if num == 2:
return True
elif num % 2 == 0 or num < 2:
return False
else:
for i in range(3, math.isqrt(num) + 1, 2):
if num % i == 0:
return False
return True
N = int(input())
tops = [int(input()) for _ in range(N)]
K = int(input())
ids = [int(input()) for _ in range(K)]
# 使用字典存储排名信息和查询状态
rank_dict = {top: i + 1 for i, top in enumerate(tops)}
already_got = set()
# 使用集合存储有效的ID,以加快查找速度
valid_ids = set(tops)
for current_id in ids:
print(f"{str(current_id).zfill(4)}: ", end='')
if current_id not in valid_ids:
print("Are you kidding?")
elif current_id in already_got:
print("Checked")
else:
rank = rank_dict[current_id]
if rank == 1:
print("Mystery Award")
elif is_prime(rank):
print("Minion")
else:
print("Chocolate")
already_got.add(current_id)
代码解释
- 输入处理:读取排名列表和查询ID列表。
- 字典初始化:使用字典推导式初始化 rank_dict,使用集合 valid_ids 存储有效的ID。
- 查询处理:使用集合 already_got 来记录已经查询过的ID,避免重复计算。
时间复杂度分析
- 输入处理:O(N + K)。
- 字典和集合初始化:O(N)。
- 查询处理:每个查询ID的检查时间复杂度是 O(1),因此总的时间复杂度是 O(K)。
综合来看,整个代码的时间复杂度是 O(N + K)。
空间复杂度分析
- 输入存储:O(N + K)。
- 字典和集合存储:O(N)。
综合来看,整个代码的空间复杂度是 O(N + K)。
总结
通过使用集合来存储有效的ID和已经查询过的ID,减少了不必要的字典,提高了查找速度。整体代码的时间复杂度和空间复杂度仍然是 O(N + K),但在实际运行中,由于集合的高效查找特性,性能会有所提升。
哲学和编程思想
这些优化方法体现了多个哲学和编程思想,具体包括:
-
抽象与封装:
- 抽象:将问题分解为更小的、可管理的部分,例如将输入处理、字典初始化和查询处理分开。
- 封装:将功能封装在函数中,例如 is_prime 函数,使得代码更模块化和可重用。
-
效率与优化:
- 效率:通过使用集合(set)来快速检查元素是否存在,提高了查找效率。
- 优化:避免重复计算,例如使用 already_got 集合来记录已经查询过的ID,避免重复处理。
-
简洁与清晰:
- 简洁:使用字典推导式和集合来简化代码,减少冗余。
- 清晰:代码结构清晰,易于理解和维护。
-
不变性与可变性:
- 不变性:尽量使用不可变数据结构,例如集合(set),以减少副作用和提高代码的稳定性。
- 可变性:在必要时使用可变数据结构,例如 already_got 集合,以记录状态变化。
-
DRY原则(Don't Repeat Yourself):
- 避免重复代码,例如通过使用集合来统一处理ID的检查和记录。
-
KISS原则(Keep It Simple, Stupid):
- 保持代码简单,避免过度设计,例如使用简单的数据结构和直接的逻辑处理。
-
YAGNI原则(You Ain't Gonna Need It):
- 仅实现当前需要的功能,避免过度工程化,例如不预先设计复杂的数据结构,而是根据实际需求逐步优化。
-
单一职责原则(Single Responsibility Principle):
- 每个函数或模块只负责一个功能,例如 is_prime 函数只负责判断素数,rank_dict 只负责存储排名信息。
-
开闭原则(Open/Closed Principle):
- 对扩展开放,对修改关闭。例如,如果需要增加新的奖励类型,只需修改奖励类型的判断逻辑,而不需要修改整体的查询处理流程。
通过这些哲学和编程思想的应用,代码不仅在性能上得到了优化,而且在可读性、可维护性和扩展性上也得到了提升。