每日一题遇到沙比题目——Python实现PAT甲级1061 Dating(举一反三+思想解读+逐步优化)


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

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

Python-3.12.0文档解读

目录

吐槽题目

我的写法

代码分析

1. 输入处理

2. 变量初始化

3. 查找星期几和小时

4. 查找分钟

5. 输出结果

时间复杂度

空间复杂度

总结

我要更强

优化后的代码

优化分析

时间复杂度

空间复杂度

哲学和编程思想

1. KISS(Keep It Simple, Stupid)

2. DRY(Don't Repeat Yourself)

3. 提前退出(Early Exit)

4. 最小化状态(Minimize State)

5. 空间换时间(Space-Time Tradeoff)

6. 高内聚低耦合(High Cohesion and Low Coupling)

7. 单一职责原则(Single Responsibility Principle, SRP)

8. 最小惊讶原则(Principle of Least Astonishment)

举一反三

1. 简化设计

2. 消除重复

3. 提前退出

4. 最小化状态

5. 空间换时间

6. 高内聚低耦合

7. 单一职责原则

8. 最小惊讶原则



 题目链接


吐槽题目


这道题描述有问题,小时数应该是找到第一个共有的大写字母之后的那个共有字符而不是题目所描述的第二个共有字符。让我浪费1小时,无语!!!!!

我的写法

import sys

# 读取标准输入
input = sys.stdin.read

# 去除输入数据的前后空白,并按空白字符分割成列表
data = input().strip().split()

# 将输入的四个字符串分别赋值给 first_str、second_str、third_str 和 fourth_str
first_str = data[0]
second_str = data[1]
third_str = data[2]
fourth_str = data[3]

# 初始化存储星期几、小时和分钟的变量
weekday = ""
hour = ""
minute = ""

# 定义一个列表,包含星期一到星期日的缩写
days = ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"]

# 布尔变量,用于指示是否已找到第一个匹配的大写字母
found_first = False

# 遍历 first_str 和 second_str 中每个字符的位置(长度取两者的最小值)
for i in range(min(len(first_str), len(second_str))):
    # 如果两个字符串在某位置的字符相同
    if first_str[i] == second_str[i]:
        # 如果还未找到第一个大写字母且该字符在 'A' 到 'G' 之间
        if not found_first and 'A' <= first_str[i] <= 'G':
            # 将 weekday 设为相应的星期几(通过 days 列表和字符的 ASCII 码计算得出)
            weekday = days[ord(first_str[i]) - ord('A')]
            # 更新 found_first 为 True
            found_first = True
        # 如果已找到第一个大写字母
        elif found_first:
            # 如果该字符是数字 '0' 到 '9' 之间,将其转换为整数并赋值给 hour
            if '0' <= first_str[i] <= '9':
                hour = int(first_str[i])
                break
            # 如果该字符是 'A' 到 'N' 之间,将其转换为对应的小时值并赋值给 hour(通过字符的 ASCII 码计算得出)
            elif 'A' <= first_str[i] <= 'N':
                hour = 10 + ord(first_str[i]) - ord('A')
                break

# 遍历 third_str 和 fourth_str 中每个字符的位置(长度取两者的最小值)
for i in range(min(len(third_str), len(fourth_str))):
    # 如果两个字符串在某位置的字符相同且该字符是字母
    if third_str[i] == fourth_str[i] and third_str[i].isalpha():
        # 将该位置的索引赋值给 minute
        minute = i
        break

# 打印结果,格式为 星期几 小时:分钟,小时和分钟都以两位数显示(不足两位的前面补零)
print(f"{weekday} {hour:02d}:{minute:02d}")

这段代码的主要功能是从四个输入字符串中解析出一个特定的时间信息,其中包括星期几、小时和分钟。代码的实现步骤包括:

  1. 读取输入数据并进行预处理。
  2. 初始化存储星期几、小时和分钟的变量。
  3. 通过遍历前两个字符串来确定星期几和小时。
  4. 通过遍历后两个字符串来确定分钟。
  5. 最终输出格式化的结果。

代码分析

1. 输入处理

python复制

input = sys.stdin.read

data = input().strip().split()

first_str = data[0]

second_str = data[1]

third_str = data[2]

fourth_str = data[3]

  • 从标准输入中读取数据,并按空白字符分割成列表形式。
  • 将列表中的四个元素分别赋值给 first_str、second_str、third_str 和 fourth_str。
2. 变量初始化

python复制

weekday =

""

hour = ""

minute = ""

days = ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"]

found_first = False

  • 初始化存储星期几、小时和分钟的变量。
  • 使用一个布尔变量 found_first 来指示是否已找到第一个匹配的大写字母。
  • days 列表包含星期一到星期日的缩写,对应字符 'A' 到 'G'。
3. 查找星期几和小时

python复制

for i in range(min(len(first_str), len(second_str))):

if first_str[i] == second_str[i]:

if not found_first and 'A' <= first_str[i] <= 'G':

weekday = days[ord(first_str[i]) - ord('A')]

found_first = True

elif found_first:

if '0' <= first_str[i] <= '9':

hour = int(first_str[i])

break

elif 'A' <= first_str[i] <= 'N':

hour = 10 + ord(first_str[i]) - ord('A')

break

  • 通过遍历 first_str 和 second_str,找到第一个匹配的字符并判断其是否在 'A' 到 'G' 之间以确定星期几。
  • 如果已找到第一个匹配字符,再寻找下一个匹配字符以确定小时。
4. 查找分钟

python复制

for i in range(min(len(third_str), len(fourth_str))):

if third_str[i] == fourth_str[i] and third_str[i].isalpha():

minute = i

break

  • 通过遍历 third_str 和 fourth_str,找到第一个匹配的字母以确定分钟。
5. 输出结果

python复制

print(f"{weekday} {hour:02d}:{minute:02d}")

  • 按指定格式输出结果,确保小时和分钟都以两位数显示。

时间复杂度

  • 遍历 first_str 和 second_str 的长度取决于较短的字符串长度,时间复杂度为 O(n)。
  • 遍历 third_str 和 fourth_str 的长度也是取决于较短的字符串长度,时间复杂度为 O(m)。
  • 总体时间复杂度为 O(n + m),其中 n 和 m 分别是两组字符串的最小长度。

空间复杂度

  • 变量 weekday、hour 和 minute 以及 found_first 和 days 列表占用常数空间。
  • 额外使用的空间主要是输入数据存储,假设输入数据长度为 k,则空间复杂度为 O(k)。
  • 总体空间复杂度为 O(k)。

总结

这段代码在时间复杂度和空间复杂度上都表现良好,能够高效地处理输入数据并解析出所需的时间信息。代码结构清晰,逻辑合理,适用于输入规模较大的场景。


我要更强

在这段代码中,时间复杂度和空间复杂度已经相对较优。但是,我们可以通过减少冗余操作和更精简的逻辑来进一步优化。以下是一些优化的思路:

  1. 合并变量初始化和输入读取:减少不必要的分步骤操作。
  2. 合并遍历逻辑:将查找星期几和小时的遍历合并,减少循环次数。
  3. 减少空间占用:尽可能使用局部变量和避免重复存储来减少空间复杂度。
  4. 提前终止循环:一旦找到所需的字符,即可提前退出循环,避免多余的遍历。

优化后的代码

import sys

# 读取标准输入并处理
input = sys.stdin.read().strip().split()
first_str, second_str, third_str, fourth_str = input

# 定义星期几的列表
days = ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"]

# 初始化变量
weekday = ""
hour = ""
minute = ""

# 用于标记是否找到了第一个大写字母
found_first = False

# 遍历 first_str 和 second_str,长度取两者的最小值
for i in range(min(len(first_str), len(second_str))):
    if first_str[i] == second_str[i]:
        if not found_first:
            if 'A' <= first_str[i] <= 'G':
                weekday = days[ord(first_str[i]) - ord('A')]
                found_first = True
        else:
            if '0' <= first_str[i] <= '9':
                hour = int(first_str[i])
                break
            elif 'A' <= first_str[i] <= 'N':
                hour = 10 + ord(first_str[i]) - ord('A')
                break

# 遍历 third_str 和 fourth_str,长度取两者的最小值
for i in range(min(len(third_str), len(fourth_str))):
    if third_str[i] == fourth_str[i] and third_str[i].isalpha():
        minute = i
        break

# 打印格式化结果
print(f"{weekday} {hour:02d}:{minute:02d}")

优化分析

时间复杂度
  • 对于查找星期几和小时的循环,时间复杂度仍然是 O(n),其中 n 是 first_str 和 second_str 的最小长度。
  • 对于查找分钟的循环,时间复杂度仍然是 O(m),其中 m 是 third_str 和 fourth_str 的最小长度。
  • 综合时间复杂度依旧是 O(n + m),但通过合并逻辑和提前终止循环,提升了实际运行效率。
空间复杂度
  • 输入数据的存储空间复杂度为 O(k),其中 k 是输入字符串的总长度。
  • 其他变量如 weekday、hour、minute 等占用常数空间。
  • 总体空间复杂度为 O(k),并没有增加额外的存储需求。

通过这些优化,减少了冗余操作,使得代码更加简洁高效。在处理大规模输入数据时,优化后的代码将更加高效。


哲学和编程思想

在这段代码的优化过程中,应用了一些重要的哲学和编程思想。以下是具体说明:

1. KISS(Keep It Simple, Stupid)

这是一种设计原则,强调简单性。简单的设计更容易理解、维护和调试。

  • 应用:通过减少不必要的分步骤操作(如合并变量初始化和输入读取),使代码更加简洁和直接。

2. DRY(Don't Repeat Yourself)

这是一个编程原则,旨在减少代码重复,提高代码的可维护性。

  • 应用:通过合并遍历逻辑,将查找星期几和小时的循环合并,避免了重复的遍历操作。

3. 提前退出(Early Exit)

这一原则建议在满足某些条件后立即退出循环或函数,以避免不必要的计算。

  • 应用:在找到所需的字符后立即退出循环,减少无效的遍历操作。

4. 最小化状态(Minimize State)

这一原则建议在程序中尽量减少需要维护的状态变量,以简化程序逻辑。

  • 应用:通过减少全局变量的使用,尽量使用局部变量,这样可以降低程序的复杂性和出错概率。

5. 空间换时间(Space-Time Tradeoff)

这一思想在算法设计中非常重要,它指出我们可以通过使用更多的空间来减少时间复杂度,反之亦然。

  • 应用:在这个优化过程中,我们通过使用局部变量减少了空间复杂度,但在时间复杂度上没有做出牺牲,因为空间换时间在这里并不适用。

6. 高内聚低耦合(High Cohesion and Low Coupling)

这一原则强调模块内部应高度相关,而模块之间的依赖应尽量减少。

  • 应用:通过将功能逻辑集中在一起(如将输入处理、变量初始化和遍历逻辑合并),提高了代码的内聚性,减少了模块间的依赖。

7. 单一职责原则(Single Responsibility Principle, SRP)

每个模块或函数应该只有一个职责或功能,这样更容易理解和维护。

  • 应用:每个循环只负责一个具体的任务(一个负责查找星期几和小时,另一个负责查找分钟),使得代码更具可读性和可维护性。

8. 最小惊讶原则(Principle of Least Astonishment)

代码应当以一种最不让人感到惊讶的方式工作,使用常见的约定和直观的方式来实现功能。

  • 应用:通过使用直观的变量名和清晰的逻辑,使得代码更容易理解,不会让读者感到困惑。

通过这些优化和编程思想的应用,代码不仅在性能上得到了提升,而且在可读性、可维护性和可靠性上也得到了增强。


举一反三

当然,可以通过理解这些编程原则,将它们灵活应用于不同的场景,来提升编程技能。以下是一些技巧,帮助你更好地举一反三:

1. 简化设计

技巧: 在设计代码时,先从最简单的方案入手,然后逐步添加复杂性。

  • 实践: 在写函数时,先写出主要逻辑,然后再考虑异常处理和边界条件。

2. 消除重复

技巧: 在编码过程中,时刻警惕重复的代码片段,考虑是否能将其抽象为函数或模块。

  • 实践: 定期审查代码,寻找重复的逻辑,并尝试将其重构为通用函数。

3. 提前退出

技巧: 在循环或判断中,一旦满足条件,就立即退出,避免不必要的计算。

  • 实践: 在编写循环和条件判断时,优先考虑提前退出策略(如return、break、continue等)。

4. 最小化状态

技巧: 尽量避免使用全局变量,优先使用局部变量,保持代码的独立性。

  • 实践: 在函数内部定义变量,确保这些变量只在函数内部使用。

5. 空间换时间

技巧: 当需要优化性能时,分析是否可以通过增加空间消耗来减少时间复杂度。

  • 实践: 在处理大数据集时,考虑使用哈希表(字典)来快速查找,提高查询速度。

6. 高内聚低耦合

技巧: 设计模块时,确保模块内部的功能高度相关,同时减少模块之间的依赖关系。

  • 实践: 使用面向对象的编程(OOP)思想,将相关功能封装到类中,并通过接口减少耦合。

7. 单一职责原则

技巧: 确保每个函数或模块只负责一项功能,避免职责过多导致代码复杂化。

  • 实践: 在编写函数时,明确函数的单一职责,并将不同功能拆分为多个小函数。

8. 最小惊讶原则

技巧: 使用常见的编程约定和清晰的命名,确保代码易于理解和维护。

  • 实践: 遵循团队的代码风格指南,使用通俗易懂的变量名和函数名。

通过这些技巧,可以在多种编程场景中灵活应用上述原则,使代码更简洁、高效、易于维护。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/686411.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt for android : 调用 OpenCV库错误集(To Be Continue)

error: error: undefined symbol: AMediaExtractor_new 在调用 VideoCapture等库时出现 解决: LIBS -lmediandk

UE5-AI

AI角色 角色控制器 AI角色必须要一个角色控制器 角色控制器最基本只需要执行行为树&#xff0c;在EventOnPossess后runBehaviorTree 如果要的是一个角色&#xff0c;可以创建一个Character&#xff0c;在类默认设置中可以找到 Pawn->AIControllerClass&#xff0c;在这里…

Golang | Leetcode Golang题解之第136题只出现一次的数字

题目&#xff1a; 题解&#xff1a; func singleNumber(nums []int) int {single : 0for _, num : range nums {single ^ num}return single }

Flink任务如何跑起来之 1.DataStream和Transformation

Flink任务如何跑起来之 1.DataStream和Transformation 1. 滥觞 在使用Flink完成业务功能之余&#xff0c;有必要了解下我们的任务是如何跑起来的。知其然&#xff0c;知其所以然。 既然重点是学习应用程序如何跑起来&#xff0c;那么应用程序的内容不重要&#xff0c;越简单…

动手学深度学习——Kaggle小白入门

1. kaggle注册 注册网址&#xff1a;https://www.kaggle.com 注册账号不需要代理&#xff0c;但手机号验证需要代理。如果要使用GPU或TPU&#xff0c;则需要进行手机号验证。 手机号验证位置&#xff1a;右上角头像的settings界面。 手机号验证时会有几个问题&#xff1a; …

【栈】1096. 花括号展开 II

本文涉及知识点 栈 LeetCode 1096. 花括号展开 II 如果你熟悉 Shell 编程&#xff0c;那么一定了解过花括号展开&#xff0c;它可以用来生成任意字符串。 花括号展开的表达式可以看作一个由 花括号、逗号 和 小写英文字母 组成的字符串&#xff0c;定义下面几条语法规则&…

服务器数据恢复—raid5阵列磁盘坏道离线导致数据丢失的数据恢复案例

服务器数据恢复环境&#xff1a; 某品牌x3850 X5服务器&#xff0c;服务器上有一组由5块硬盘组建的raid5阵列&#xff08;包含一块热备盘&#xff09;&#xff0c;安装linux操作系统&#xff0c;运行oracle数据库。 服务器故障&#xff1a; 服务器上raid5阵列中两块硬盘由于未…

【Linux操作系统】进程状态(1)

&#x1f389;博主首页&#xff1a; 有趣的中国人 &#x1f389;专栏首页&#xff1a; Linux &#x1f389;其它专栏&#xff1a; C初阶 | C进阶 | 初阶数据结构 小伙伴们大家好&#xff0c;本片文章将会讲解 Linux操作系统 进程状态 的相关内容。 如果看到最后您觉得这篇文章…

HDFS 之 DataNode 核心知识点

优质博文&#xff1a;IT-BLOG-CN 一、DataNode工作机制 DataNode工作机制&#xff0c;如下所示&#xff1a; 【1】一个数据块在 DataNode上以文件形式存储在磁盘上&#xff0c;包括两个文件&#xff0c;一个是数据本身&#xff0c;一个是元数据包括数据块的长度&#xff0c…

Codeforces Round 951 (Div. 2)(A~C)

目录 A. Guess the Maximum B. XOR Sequences C. Earning on Bets 这次比赛也是打的稀碎了&#xff0c;第二个少个break检查了15分钟才检查出来&#xff0c;第三个符号搞错了&#xff0c;错了两次&#xff0c;道心直接破碎了 A. Guess the Maximum 题意&#xff1a;我们对…

计算机组成原理-cache详解

一、Cache的概念和原理 1、cache原理 2、cache性能分析 一道例题 3、cache和主存数据交换的单位 每次访问到的主存块会立即放入cache中 小结 二、cache和主存之间的映射关系 全相联映射 全相联访存过程 直接映射 组相联映射 小结 三、cache替换算法 在直接映射中&#xff0c…

webgl_framebuffer_texture

ThreeJS 官方案例学习&#xff08;webgl_framebuffer_texture&#xff09; 1.效果图 2.源码 <template><div><div id"container"></div><div id"selection"><div></div></div></div> </templa…

【sklearn】【逻辑回归1】

学习笔记来自&#xff1a; 所用的库和版本大家参考&#xff1a; Python 3.7.1Scikit-learn 0.20.1 Numpy 1.15.4, Pandas 0.23.4, Matplotlib 3.0.2, SciPy 1.1.0 1 概述 1.1 名为“回归”的分类器 在过去的四周中&#xff0c;我们接触了不少带“回归”二字的算法&#xf…

IDEA破解后的配置

以下所有操作都要求进入全局setting而不是某一个项目的setting 进入全局Setting File→close project 进入欢迎页面 低版本 然后点击Setting 关闭自动更新 不关闭有可能会破解失败 Appearance & Behavior->System Settings->Updates下取消Automatically chec…

k8s 对外服务之 Ingress(HTTPS/HTTP 代理访问 以及Nginx 进行 BasicAuth )

目录 一 Ingress HTTP 代理访问虚拟主机 &#xff08;一&#xff09;原理 &#xff08;二&#xff09;实验 1&#xff0c;准备 2&#xff0c;创建虚拟主机1资源 3&#xff0c;创建虚拟主机2资源 4&#xff0c;创建ingress资源 5&#xff0c;查看相关参数 6&#xff0…

ai写作工具哪些好用,分享4种ai智能写作软件

当我们踏入这个充满创意与无限可能的自媒体时代&#xff0c;ai写作工具就如同一盏盏闪耀的明灯&#xff0c;照亮我们的创作之路。那么&#xff0c;市面上的ai写作工具哪些好用呢&#xff1f;对于这个问题&#xff0c;今天&#xff0c;本文就带领大家一同揭开那神秘的面纱&#…

编译等底层知识

目录 一. GCC命令语句大全 二. GCC编译4个阶段 三. makefile的使用 四. CMake 五. GNU工具链开发流程图 六. Keil中的地址段 七. 静态库和动态库 一. GCC命令语句大全 -c只编译源文件&#xff0c;生成目标文件&#xff08;.o 文件&#xff09;&#xff0c;不进行链接。…

如何查询公网IP?

在互联网中&#xff0c;每个设备都有一个唯一的公网IP地址&#xff0c;用于标识设备在全球范围内的位置。查询公网IP是一个常见的需求&#xff0c;无论是用于远程访问、网络配置还是其他目的&#xff0c;了解自己的公网IP地址都是很有必要的。本文将介绍几种常见的方法来查询公…

Java并发编程中Future使用

Future类有什么用 Future类是异步思想的典型应用&#xff0c;主要用在一些需要执行耗时任务的场景&#xff0c;避免程序一直原地等待耗时任务完成&#xff0c;执行效率太低。具体来说&#xff1a;**当我们执行某一个耗时的任务时&#xff0c;可以将这个耗时任务交给一个子线程…

python3 -m http.server 检查打包前端的项目

python3 -m http.server这是 Python 提供的一个内置的简单 HTTP 服务器。当你在终端中运行 python3 -m http.server 命令时(在对应的打包目录比如dist目录)&#xff0c;Python 会启动一个 HTTP 服务器&#xff0c;它会将当前工作目录下的文件作为静态文件提供给浏览器。这个服务…