每日一题——Python实现PAT甲级1058 A+B in Hogwarts(举一反三+思想解读+逐步优化)


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

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

Python-3.12.0文档解读

目录

我的写法

代码点评:

时间复杂度分析:

空间复杂度分析:

总结:

我要更强

时间复杂度分析:

空间复杂度分析:

哲学和编程思想

举一反三

1. 简化设计(KISS原则)

2. 避免重复(DRY原则)

3. 数据结构和算法选择

4. 编写可维护的代码

5. 函数式编程思想

6. 抽象和封装


 题目链接


我的写法

# 从标准输入读取一行,使用空格分割输入,得到两个字符串A和B
A, B = input().split()

# 将字符串A按照点分割,并使用map函数将分割后的字符串转换为整数列表
A = list(map(int, A.split('.')))

# 将字符串B按照点分割,并使用map函数将分割后的字符串转换为整数列表
B = list(map(int, B.split('.')))

# 初始化一个长度为3的列表output,用于存储计算结果
output = [0, 0, 0]

# 计算最低位(第3位)的和,并处理进位
output[2] += (A[2] + B[2]) % 29

# 将最低位的和除以29,并将商加到第2位(output[1])
output[1] += (A[2] + B[2]) // 29

# 计算第2位的和,并处理进位
output[1] += (A[1] + B[1]) % 17

# 如果第2位的和大于等于17,则将商加到第1位(output[0]),并对第2位取余
if output[1] >= 17:
    output[0] += output[1] // 17
    output[1] %= 17

# 将第2位的和除以17,并将商加到第1位(output[0])
output[0] += (A[1] + B[1]) // 17

# 将最高位(第1位)的和直接加到output[0]
output[0] += A[0] + B[0]

# 打印输出结果,使用点作为分隔符
print(*output, sep='.')

这段代码实现了一个特定进制的加法运算,其中最低位(第3位)的进制是29,次低位(第2位)的进制是17,最高位(第1位)是十进制。代码通过读取用户输入的两个数字字符串,分别解析为整数列表,然后进行加法运算,并处理进位,最后输出结果。

代码点评:

  1. 输入处理:代码首先使用input().split()读取用户输入,并将输入分割为两个部分。然后,每个部分再次使用split('.')分割,并将分割后的字符串转换为整数列表。这种处理方式简洁高效,适合处理格式化的输入。
  2. 进制转换和加法运算:代码通过模拟手工加法的过程来处理不同进制的加法,包括进位的处理。这种实现方式直观易懂,但可能对于不熟悉进制转换的读者来说,代码的逻辑可能需要一些时间来理解。
  3. 输出格式:代码使用print(*output, sep='.')来输出结果,这种方式简洁且符合Python的输出习惯,使得输出结果清晰易读。

时间复杂度分析:

  • 输入处理:input().split()和split('.').map(int)的时间复杂度都是O(n),其中n是输入字符串的长度。
  • 加法运算:加法运算的时间复杂度是O(1),因为只有固定数量的操作(3个位置的加法和进位处理)。
  • 输出:输出的时间复杂度是O(1)。

因此,总的时间复杂度是O(n),主要由输入处理决定。

空间复杂度分析:

  • 输入处理:需要存储两个分割后的字符串,空间复杂度是O(n)。
  • 加法运算:需要存储结果,空间复杂度是O(1),因为结果列表的长度固定为3。

总的空间复杂度是O(n),主要由输入处理决定。

总结:

这段代码在处理特定进制的加法运算时表现良好,时间复杂度和空间复杂度都相对较低。代码的实现简洁,逻辑清晰,适合处理格式化的输入和输出。然而,对于不熟悉进制转换的读者来说,代码的逻辑可能需要一些时间来理解。


我要更强

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

  1. 减少不必要的字符串转换:直接从输入中提取数字,而不是先转换为字符串再转换为整数。
  2. 使用更紧凑的数据结构:例如,使用元组或类来存储数据,而不是列表。
  3. 优化输入处理:一次性读取和处理输入,减少重复操作。

下面是优化后的代码实现:

# 定义进制
BASE_2 = 29
BASE_1 = 17

# 读取输入并直接处理为整数
A, B = input().split()
A = tuple(map(int, A.split('.')))
B = tuple(map(int, B.split('.')))

# 初始化结果
result = [0, 0, 0]

# 计算最低位(第3位)的和,并处理进位
result[2] = (A[2] + B[2]) % BASE_2
carry = (A[2] + B[2]) // BASE_2

# 计算第2位的和,并处理进位
result[1] = (A[1] + B[1] + carry) % BASE_1
carry = (A[1] + B[1] + carry) // BASE_1

# 计算最高位(第1位)的和
result[0] = A[0] + B[0] + carry

# 输出结果
print(f"{result[0]}.{result[1]}.{result[2]}")

时间复杂度分析:

  • 输入处理:仍然是O(n),但减少了不必要的转换操作。
  • 加法运算:仍然是O(1)。
  • 输出:仍然是O(1)。

总的时间复杂度保持为O(n)。

空间复杂度分析:

  • 输入处理:使用元组代替列表,空间复杂度仍然是O(n),但元组更紧凑。
  • 加法运算:空间复杂度是O(1)。

总的空间复杂度保持为O(n)。

优化总结: 这段代码通过减少不必要的字符串转换和使用更紧凑的数据结构,提高了代码的效率和可读性。时间复杂度和空间复杂度保持不变,但代码的执行效率有所提高。


哲学和编程思想

这段代码的优化过程中体现了以下哲学和编程思想:

  1. KISS原则(Keep It Simple, Stupid): 优化后的代码更加简洁,减少了不必要的复杂性。例如,直接使用元组来存储输入数据,而不是列表,这使得代码更易于理解和维护。
  2. DRY原则(Don't Repeat Yourself): 原代码中有重复的字符串分割和整数转换操作,优化后的代码通过一次性处理输入,避免了重复的代码,减少了出错的可能性。
  3. 抽象和封装: 通过定义常量BASE_2和BASE_1来抽象进制,使得代码更加模块化和可读。这种抽象有助于隐藏实现细节,使代码更加清晰。
  4. 数据结构的选择: 使用元组而不是列表来存储数据,反映了对于数据结构选择的考虑。元组在Python中是不可变的,这可以带来一定的性能优势,并且在某些情况下,使用元组可以减少内存使用。
  5. 函数式编程思想: 使用map函数和元组,体现了函数式编程的一些特点,如避免副作用和使用不可变数据结构。这种编程风格有助于编写更清晰、更易于测试的代码。
  6. 优化和性能考虑: 通过减少字符串转换的次数和使用更紧凑的数据结构,代码在保持相同时间复杂度和空间复杂度的同时,可能会有更好的性能表现。
  7. 可读性和可维护性: 代码的优化不仅关注性能,还关注代码的可读性和可维护性。通过简化逻辑和使用清晰的变量名,使得代码更易于理解,这对于长期维护和团队合作非常重要。

这些哲学和编程思想在软件开发中非常重要,它们有助于提高代码质量,减少错误,并提升开发效率。在实际编程中,根据具体情况灵活运用这些原则,可以编写出更加高效、健壮和易于维护的代码。


举一反三

当你在编程或设计软件系统时,以下是一些基于前述哲学和编程思想的实用技巧,可以帮助你提高代码质量和开发效率:

1. 简化设计(KISS原则)

  • 减少层次复杂度:尽量避免过深的继承层次和不必要的子类。使用简单的对象组合可以更容易地理解和维护代码。
  • 限制功能蔓延:每个模块或函数应该只做一件事,并做好。这使得代码更加模块化,也更容易测试和复用。

2. 避免重复(DRY原则)

  • 提取共用代码:如果你发现自己在多处编写相同的代码片段,考虑将其提取到一个单独的函数或模块中。
  • 使用循环和抽象:对于重复的模式,使用循环结构或定义更高层次的抽象,如设计模式或函数。

3. 数据结构和算法选择

  • 选择合适的数据结构:根据你的使用场景选择最合适的数据结构。例如,如果需要频繁查找,可能应选择哈希表;如果需要有序访问,则可能选择树结构。
  • 空间与时间权衡:有时候使用额外的空间可以显著减少时间复杂度(例如使用哈希表进行快速查找),视情况进行权衡。

4. 编写可维护的代码

  • 使用清晰的命名:变量、函数、类名应该清楚地表达其意图。避免使用缩写或过于抽象的名称。
  • 编写文档和注释:为复杂的逻辑或不明显的代码写下注释。同时,确保编写文档以帮助其他开发者理解你的代码。

5. 函数式编程思想

  • 不可变性:尽可能使用不可变数据结构,这可以减少bug和不可预见的副作用。
  • 无副作用的函数:尽量编写无副作用的纯函数,这样的函数不依赖于并不修改外部环境的状态。

6. 抽象和封装

  • 隐藏实现细节:通过接口和封装,隐藏模块的内部实现。这不仅可以保护数据,还可以在不影响使用者的情况下更改实现。
  • 设计模式的应用:合理应用设计模式可以解决常见的软件设计问题。例如,观察者模式可以用于实现事件驱动的通信。

将这些技巧运用到日常的开发实践中,可以帮助你编写出更高效、更可读、更健壮的代码。同时,这也有助于提高个人和团队的开发效率,确保软件项目的成功。


感谢阅读。

最近更新

  1. TCP协议是安全的吗?

    2024-06-06 14:44:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-06 14:44:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-06 14:44:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-06 14:44:02       18 阅读

热门阅读

  1. 如何评价GPT-4o?

    2024-06-06 14:44:02       7 阅读
  2. linux dtb解析方法之验证修改的dts是否有效

    2024-06-06 14:44:02       10 阅读
  3. 默认路由,直接路由,静态路由,动态路由

    2024-06-06 14:44:02       10 阅读
  4. 数据库服务器的三种数据结构

    2024-06-06 14:44:02       5 阅读
  5. JVM学习-自定义类加载器

    2024-06-06 14:44:02       7 阅读