欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > 每日一题——Python实现PAT甲级1108 Finding Average(举一反三+思想解读+逐步优化)

每日一题——Python实现PAT甲级1108 Finding Average(举一反三+思想解读+逐步优化)

2024/11/30 20:49:47 来源:https://blog.csdn.net/weixin_44915521/article/details/139621150  浏览:    关键词:每日一题——Python实现PAT甲级1108 Finding Average(举一反三+思想解读+逐步优化)


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

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

Python-3.12.0文档解读

目录

我的写法

时间复杂度

空间复杂度

总结

我要更强

优化点

优化后的代码

优化分析

总结

哲学和编程思想

1. 模块化设计

2. 异常处理

3. 减少冗余

4. 高内聚低耦合

5. 面向接口编程

6. 输入数据的预处理

总结

举一反三

1. 模块化设计

2. 异常处理

3. 减少冗余

4. 高内聚低耦合

5. 面向接口编程

6. 输入数据的预处理

7. 使用高效的数据结构

总结


 题目链接

我的写法

import math
N=int(input())
nums=input().split()
legal_num=N
output=0.0
for i in range(N):if nums[i].isalpha() or nums[i].count('.')>1:print(f"ERROR: {nums[i]} is not a legal number")legal_num-=1elif float(nums[i])<-1000 or float(nums[i])>1000:print(f"ERROR: {nums[i]} is not a legal number")legal_num-=1elif nums[i].count('.')==1 and len(nums[i].partition('.')[2])>2:print(f"ERROR: {nums[i]} is not a legal number")legal_num-=1else:output+=float(nums[i])
if legal_num==0:print("The average of 0 numbers is Undefined")
elif legal_num==1:print(f"The average of 1 number is {output:.2f}")
else:output/=legal_numprint(f"The average of {legal_num} numbers is {output:.2f}")

时间复杂度

代码的时间复杂度主要由以下部分决定:

  • 读取输入:O(N)
  • 遍历每一个输入并验证合法性:O(N)
  • 打印输出信息:O(1)

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

空间复杂度

代码的空间复杂度主要由以下部分决定:

  • 存储输入数值字符串的列表 nums:O(N)
  • 存储一些常量(如 legal_num 和 output):O(1)

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

总结

这段代码实现了对输入数值的合法性检测和平均值计算,逻辑清晰,操作简单。时间复杂度和空间复杂度均为 O(N),适用于输入数据量较大的情况。需要注意的是,这段代码假设输入的初始 N 和数值字符串是有效的,未处理可能的输入异常(如非整数的 N)。


我要更强

考虑到这段代码的主要功能是读取并处理输入字符串来计算平均值,其时间复杂度和空间复杂度已经较为高效,但仍有一些优化和改进的空间。

优化点

  1. 合并条件检查:减少重复的条件检查。
  2. 减少冗余计算:避免重复调用某些函数。
  3. 异常处理优化:对于转换为浮点数的操作,可以通过异常捕获来简化条件判断。

优化后的代码

def is_legal_number(num):try:# 尝试将 num 转换为浮点数val = float(num)# 检查数值范围if val < -1000 or val > 1000:return False# 检查小数点后的位数if '.' in num and len(num.split('.')[1]) > 2:return Falsereturn Trueexcept ValueError:# 转换失败说明不是合法的数字return Falsedef main():import sysinput = sys.stdin.readdata = input().split()N = int(data[0])nums = data[1:N+1]legal_num = 0output = 0.0for num in nums:if is_legal_number(num):output += float(num)legal_num += 1else:print(f"ERROR: {num} is not a legal number")if legal_num == 0:print("The average of 0 numbers is Undefined")elif legal_num == 1:print(f"The average of 1 number is {output:.2f}")else:output /= legal_numprint(f"The average of {legal_num} numbers is {output:.2f}")if __name__ == "__main__":main()

优化分析

整体时间复杂度仍然是 O(N),因为我们仍然需要遍历输入的每一个数值并进行合法性检查。

  1. 时间复杂度优化:
    • 使用 try-except 块简化了条件检查,减少了冗余的检查次数。
    • 通过 split 函数直接拆分输入,避免了多次调用相同的字符串操作函数。
  2. 空间复杂度优化:
  • 使用 sys.stdin.read 一次性读取输入数据并拆分,避免了多次读取操作,这减少了内存的额外使用。
  • 函数 is_legal_number 封装了合法性检查逻辑,使得代码更加模块化和易读。

整体空间复杂度仍然是 O(N),因为需要存储输入的数值字符串列表。

总结

通过以上优化,使代码更加模块化和简洁,减少了冗余的条件检查,并保持了整体的时间和空间复杂度。这些改进使代码更具有可读性和可维护性。


哲学和编程思想

在优化代码的过程中,运用了多种编程哲学和思想,这不仅使代码更加高效,还提高了其可读性和可维护性。以下是详细说明:

1. 模块化设计

哲学和思想

  • 单一职责原则 (Single Responsibility Principle):每个函数只有一个明确的职责。
  • 模块化 (Modularity):将不同功能封装在独立的模块中。

具体应用

  • 将合法性检查封装在 is_legal_number 函数中,使得主函数 main 更加简洁和清晰。

2. 异常处理

哲学和思想

  • 防御性编程 (Defensive Programming):通过异常处理来捕捉并处理潜在的错误。
  • 优雅退化 (Fail Gracefully):在遇到错误时,程序能够优雅地处理而不是崩溃。

具体应用

  • 使用 try-except 块来捕捉非数值输入带来的异常,避免了多次条件检查。

3. 减少冗余

哲学和思想

  • 不重复自己 (Don't Repeat Yourself, DRY):减少代码中的重复部分。
  • 简洁性 (Simplicity):保持代码简洁,避免不必要的复杂性。

具体应用

  • 合并条件检查,避免重复进行多次浮点转换和字符串操作。

4. 高内聚低耦合

哲学和思想

  • 高内聚 (High Cohesion):相关的功能放在一起,使得代码模块能够自洽地完成其职责。
  • 低耦合 (Low Coupling):模块之间的依赖性低,修改一个模块不会影响到其他模块。

具体应用

  • 合法性检查与输入输出分离,使得这两个部分互不依赖,可以独立测试和修改。

5. 面向接口编程

哲学和思想

  • 面向接口编程 (Programming to an Interface):通过接口来定义功能,而不是具体实现。
  • 抽象 (Abstraction):隐藏实现细节,只暴露必要的功能。

具体应用

  • is_legal_number 函数定义了一个接口,用于检查数值是否合法,具体的实现细节被隐藏在函数内部。

6. 输入数据的预处理

哲学和思想

  • 前期筛选 (Preprocessing):在正式处理前对数据进行预处理,避免在后续操作中反复处理同样的数据。

具体应用

  • 使用 sys.stdin.read 一次性读取所有输入数据,拆分后再处理,减少了多次读取输入的开销。

总结

通过这些编程哲学和思想,不仅优化了代码的性能,还提高了其可读性和可维护性。模块化设计、异常处理、减少冗余、高内聚低耦合、面向接口编程和输入数据的预处理等思想在代码中得到了具体体现。这些理念不仅帮助我们编写出高质量的代码,也为后续的维护和扩展奠定了坚实的基础。


举一反三

运用编程哲学和思想可以帮助你编写高质量、易维护的代码。以下是一些具体技巧和实践,帮助你在日常编程中举一反三,灵活运用这些思想:

1. 模块化设计

技巧

  • 功能分解:将每个功能块拆分成独立的函数或类,确保每个函数/类只负责一个任务。
  • 定义清晰接口:为每个模块定义清晰的接口,只暴露必要的功能。
  • 避免大函数:如果一个函数超过20-30行代码,考虑拆分成多个更小的函数。

2. 异常处理

技巧

  • 防御性编程:在可能发生错误的地方进行异常处理,防止错误蔓延。
  • 优雅退化:在捕获异常后尽可能提供有用的错误信息,并保持程序继续运行。

3. 减少冗余

技巧

  • 不重复自己 (DRY):提取重复的代码片段到函数中,避免在多个地方出现相同代码。
  • 使用数据结构和库函数:尽量使用高效的数据结构和库函数,避免自己实现复杂的逻辑。

4. 高内聚低耦合

技巧

  • 高内聚:确保一个模块或类内的功能紧密相关,单一职责。
  • 低耦合:模块之间的依赖性尽量低,不要轻易引用其他模块的实现细节。

5. 面向接口编程

技巧

  • 编程面向接口:通过接口(函数、类方法)来定义模块的功能,而不是直接实现细节。
  • 抽象层次:通过抽象层次来隐藏实现细节,只暴露必要的接口。

6. 输入数据的预处理

技巧

  • 提前预处理:在正式处理数据之前,先进行必要的预处理,以减少后续步骤中的重复工作。
  • 数据清洗:确保数据在进入逻辑处理之前已经被清洗和验证。

7. 使用高效的数据结构

技巧

  • 选择合适的数据结构:根据具体问题选择高效的数据结构,如列表、集合、字典等。
  • 避免不必要的拷贝:尽量避免在循环中频繁创建或拷贝数据。

总结

通过运用这些技巧和实践,可以在编写代码时灵活应用编程哲学和思想,提高代码的质量和可维护性。这些技巧不仅有助于解决当前问题,还能为在面对更复杂的编程挑战时提供有力的指导。


版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com