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


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

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

Python-3.12.0文档解读

目录

我的写法

优点

改进建议

时间复杂度分析

空间复杂度分析

总结

我要更强

优化方法

优化后的代码

优化分析

哲学和编程思想

1. 懒惰求值(Lazy Evaluation)

2. 缓存(Memoization)

3. 最小化冗余(Minimization of Redundancy)

4. 对称性和不变性(Symmetry and Invariance)

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

6. 分治思想(Divide and Conquer)

7. 避免重复工作(Avoiding Duplication of Work)

总结



题目链接

我的写法

N = int(input())  # 读取整数N,表示集合的数量
sets = []  # 初始化一个空列表,用于存储集合def similarity(set1, set2):# 定义一个函数 similarity,它接收两个集合 set1 和 set2 作为参数# 计算两个集合的相似度(交集大小除以并集大小,并乘以100得到百分比形式)return f"{len(set1 & set2) / len(set1 | set2) * 100:.1f}%"for i in range(N):# 循环N次,读取每个集合# 使用 split() 分割输入,忽略第一个元素(因为它是集合的序号),将剩余元素转换为集合并添加到 sets 列表中sets.append(set(input().split()[1:]))K = int(input())  # 读取整数K,表示查询的数量
for _ in range(K):# 循环K次,读取每个查询i, j = map(int, input().split())  # 读取两个整数 i 和 j,表示查询的两个集合的编号# 调用 similarity 函数计算 sets[i-1] 和 sets[j-1] 的相似度(集合编号从1开始,所以要减1)print(similarity(sets[i - 1], sets[j - 1]))

 这段代码的功能是读取多个集合并存储,计算和输出指定集合对的相似度。以下是对这段代码的专业点评和复杂度分析:

优点

  1. 简洁明了:代码逻辑清晰,结构简单,方便理解和维护。
  2. 函数封装:使用了similarity函数进行相似度计算,使代码模块化且易于复用。
  3. 直接输入处理:通过input().split()处理输入,简化了数据的读取过程。

改进建议

  1. 错误处理:代码没有处理输入的合法性和范围问题,比如负数或超出集合数量的查询。这可能导致运行时错误。
  2. 性能优化:当集合非常大时,交集和并集的计算可能会导致性能问题,可以考虑使用更高效的数据结构或算法。
  3. 注释和文档:虽然已经逐行加注释,但在实际应用中,详细的文档和函数说明也是必要的。

时间复杂度分析

  1. 读取集合:读取每个输入集合的时间复杂度为O(M),其中M是每个集合的平均大小。因此,读取N个集合的总时间复杂度为O(N * M)。
  2. 计算相似度:
    • 交集操作set1 & set2的时间复杂度为O(min(len(set1), len(set2)))。
    • 并集操作set1 | set2的时间复杂度为O(len(set1) + len(set2))。
    • 因此,单次相似度计算的时间复杂度为O(len(set1) + len(set2)),在最坏情况下是O(2M) = O(M)。
  3. 总相似度计算:有K次查询,因此所有查询的总时间复杂度为O(K * M)。

综上,总时间复杂度为: [ O(N * M + K * M) ] 在最坏情况下,N和K都非常大时可以简化为: [ O((N + K) * M) ]

空间复杂度分析

  1. 存储集合:每个集合的空间复杂度为O(M),N个集合的总空间复杂度为O(N * M)。
  2. 临时变量:交集和并集操作会创建临时集合,其空间复杂度为O(len(set1) + len(set2)),即最坏情况下是O(2M) = O(M)。

因此,总空间复杂度为: [ O(N * M) ] 这包括了存储所有集合所需的空间和计算交集并集时的临时空间。

总结

这段代码在功能实现上是正确的,但在处理大数据集时,性能和空间利用上可能需要进一步优化。可以考虑引入错误处理机制和优化集合操作的方法以提高效率。


我要更强

优化代码的时间复杂度和空间复杂度是非常重要的,对于处理大数据集尤其如此。以下是一些可能的优化方法:

优化方法

  1. 预计算:可以在读取集合时预先计算并存储每个集合的大小,这样在计算并集大小时就不需要重新计算集合的长度。
  2. 哈希表存储大小:使用哈希表存储每个集合的大小和每对集合的交集大小,可以避免重复计算。

优化后的代码

N = int(input())  # 读取整数N,表示集合的数量
sets = []  # 初始化一个空列表,用于存储集合
sizes = []  # 初始化一个空列表,用于存储每个集合的大小
intersection_sizes = {}  # 初始化一个字典,用于存储集合对的交集大小def similarity(size1, size2, intersection_size):# 定义一个函数 similarity,用于计算两个集合的相似度union_size = size1 + size2 - intersection_sizereturn f"{intersection_size / union_size * 100:.1f}%"for i in range(N):# 循环N次,读取每个集合current_set = set(input().split()[1:])  # 忽略第一个元素(因为它是集合的序号)sets.append(current_set)  # 将集合添加到sets列表中sizes.append(len(current_set))  # 存储集合的大小K = int(input())  # 读取整数K,表示查询的数量
queries = [tuple(map(int, input().split())) for _ in range(K)]  # 预先读取所有查询并存储为元组列表for i, j in queries:idx1, idx2 = min(i - 1, j - 1), max(i - 1, j - 1)  # 确保idx1 < idx2if (idx1, idx2) not in intersection_sizes:# 计算交集大小并存储在字典中intersection_size = len(sets[idx1] & sets[idx2])intersection_sizes[(idx1, idx2)] = intersection_sizeelse:intersection_size = intersection_sizes[(idx1, idx2)]# 计算并打印相似度print(similarity(sizes[idx1], sizes[idx2], intersection_size))

优化分析

优化后,总时间复杂度仍为: [ O(N * M + K * M) ] 但是在查询过程中,利用了缓存的交集大小,减少了重复计算。

  1. 时间复杂度:
    • 读取集合:与原始代码相同,时间复杂度为O(N * M)。
    • 预计算和存储大小:每个集合的大小存储一次,时间复杂度为O(N)。
    • 查询相似度:每次查询时,只需计算一次交集并存储,后续查询相同对时直接读取,时间复杂度为O(K * M)。
  2. 空间复杂度:
  • 存储集合:与原始代码相同,空间复杂度为O(N * M)。
  • 存储集合大小和交集大小:额外使用了O(N)的空间存储每个集合的大小,以及O(K)的空间存储交集大小(最坏情况下每对集合都被查询一次)。

优化后,总空间复杂度为: [ O(N * M + N + K) ]

通过这些优化,代码在处理大数据集时的性能得到了显著提升,尤其是在查询阶段通过缓存交集大小减少了重复计算,提高了效率。


哲学和编程思想

在优化代码以及改善时间复杂度和空间复杂度的过程中,我们应用了多种哲学和编程思想。以下是一些关键思想及其具体应用:

1. 懒惰求值(Lazy Evaluation)

懒惰求值是一种编程技术,它推迟计算直到真正需要结果时才进行计算。在我们的代码中,我们通过以下方式应用了懒惰求值的思想:

具体应用:

  • 预计算交集大小:只有在需要计算相似度时才计算交集大小,而不是在读取集合时就计算。
  • 缓存结果:存储已经计算过的交集大小,以避免重复计算。

示例:

if (idx1, idx2) not in intersection_sizes:intersection_size = len(sets[idx1] & sets[idx2])intersection_sizes[(idx1, idx2)] = intersection_size
else:intersection_size = intersection_sizes[(idx1, idx2)]

2. 缓存(Memoization)

缓存是一种优化技术,通过存储函数的计算结果以避免重复计算。我们的代码利用字典缓存交集大小,从而减少重复计算,提升性能。

具体应用:

  • 缓存交集大小:使用字典存储每对集合的交集大小,避免相同计算的重复。

示例:

intersection_sizes = {}  
# 初始化一个字典,用于存储集合对的交集大小

3. 最小化冗余(Minimization of Redundancy)

减少冗余是优化的一种基本原则,通过消除重复计算和数据存储,提升代码的效率。这在我们的代码中通过预计算和缓存体现出来。

具体应用:

  • 预计算集合大小:在读取集合时预先计算并存储每个集合的大小,避免在计算相似度时重复计算集合大小。

示例:

sizes.append(len(current_set))  # 存储集合的大小

4. 对称性和不变性(Symmetry and Invariance)

在处理集合对时利用对称性特性,即集合 A 与集合 B 的交集与集合 B 与集合 A 的交集是相同的,从而减少计算和存储的复杂度。

具体应用:

  • 保持索引顺序一致:通过保证 idx1 < idx2,我们利用了交集运算的对称性,简化了逻辑。

示例:

idx1, idx2 = min(i - 1, j - 1), max(i - 1, j - 1)  # 确保 idx1 < idx2

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

通过使用更多的内存来缓存计算结果,从而减少计算时间。这种技术在我们的代码中通过使用字典缓存交集大小得以体现。

具体应用:

  • 缓存交集大小:以空间换时间,通过使用字典存储交集大小提升查询效率。

示例:

intersection_sizes[(idx1, idx2)] = intersection_size

6. 分治思想(Divide and Conquer)

分治思想是将复杂问题分解成较小的子问题逐个解决。虽然在我们的具体代码中没有直接使用这种思想,但整体优化的过程包含了将读取集合、预计算、查询分解开来分别处理的思路。

具体应用:

  • 分阶段处理:将读取集合、缓存信息和查询相似度分开处理,每个阶段专注于特定任务。

示例:

for i in range(N):  # 读取集合并存储大小
for i, j in queries:  # 处理查询

7. 避免重复工作(Avoiding Duplication of Work)

通过缓存和预计算来避免重复计算,是一种高效的程序设计策略。

具体应用:

  • 预计算和缓存:上述提到的多次预计算和缓存实际应用了避免重复工作的思想。

示例:

if (idx1, idx2) not in intersection_sizes:intersection_size = len(sets[idx1] & sets[idx2])intersection_sizes[(idx1, idx2)] = intersection_size
else:intersection_size = intersection_sizes[(idx1, idx2)]

总结

这些哲学和编程思想共同作用,能够使人编写出更高效、更易维护的代码。通过懒惰求值、缓存、最小化冗余、对称性、空间换时间、分治及避免重复工作等思想,有效地优化了代码的性能。


感谢阅读。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】指针(4)

一、回顾 在这之前&#xff0c;我们学习了很多关于指针的内容&#xff0c;我们先在这里简单的回顾一下。 1、一级指针 int* p; -- 整形指针-指向整形的指针 char* p; ... void* p;... ... 2、二级指针 int** p; char** p; ... 3、数组指针 -- 指向数组的指针 int (*p)[ ]…

3038. 相同分数的最大操作数目 I(Rust模拟击败100%Rust用户)

题目 给你一个整数数组 nums &#xff0c;如果 nums 至少 包含 2 个元素&#xff0c;你可以执行以下操作&#xff1a; 选择 nums 中的前两个元素并将它们删除。 一次操作的 分数 是被删除元素的和。 在确保 所有操作分数相同 的前提下&#xff0c;请你求出 最多 能进行多少次…

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

题目&#xff1a; 题解&#xff1a; class Solution:def singleNumber(self, nums: List[int]) -> int:return reduce(lambda x, y: x ^ y, nums)

Vue07-MVVM模型

一、MVVM模型的定义 M&#xff1a;模型&#xff08;model&#xff09;&#xff1a;对应data中的数据&#xff1b;V&#xff1a;视图&#xff08;view&#xff09;&#xff1a;模版&#xff1b;VM&#xff1a;视图模型&#xff08;ViewModel&#xff09;Vue的实例对象。 Vue.js…

WSDM2022推荐系统相关论文整理(一)

2022年第15届国际网络搜索与数据挖掘会议WSDM在2022年2月21日到25日于线上举行&#xff0c;共收到了786份有效投稿&#xff0c;最终录取篇数为159篇&#xff0c;录取率为20.23%。作为主流的搜索与数据挖掘会议&#xff0c;论文的话题主要侧重于搜索、推荐以及数据挖掘领域&…

第二证券炒股知识:北交所的股票是a股吗?是主板吗?

北交所的股票是a股&#xff0c;但不属于主板&#xff0c;是一个单独的板块。 A股主板是在上海证券买卖所或许深圳证券买卖所上市的公司&#xff0c;主板通常是大盘股&#xff0c;多为商场占有率高、规划大、盈余安稳良好的大型企业。沪市主板以600、601或603最初&#xff0c;深…

(学习笔记)数据基建-数据安全

&#xff08;学习笔记&#xff09;数据基建-数据安全 数据安全数据安全实施难点数据安全保障流程数据安全措施实施阶段数据安全如何量化产出数据安全思考 数据安全 数据安全问题是最近比较热的话题&#xff0c;数据泄漏引发的用户信任危机事件也比比皆是&#xff0c;以及跨部门…

一个案例,剖析攻防演练中威胁溯源的正确姿势

一年一度的攻防演练即将拉开帷幕。“威胁溯源”一直是演练活动中一个十分重要的工作项&#xff0c;它不仅有助于理解和分析攻击的来源、方法和动机&#xff0c;还能够显著提升整体安全防护水位&#xff0c;提升组件与人员的联动协作能力。在真实的攻击场景中&#xff0c;溯源工…

verilog 232串口通信程序

1,串口通信协议: 通常串口的一次发送或接收由四个部分组成:起始位S、数据位D0~D7(一般为 6 位~8 位之间可变,数据低位在前)、校验位(奇校验、偶检验或不需要校验位)、停止位(通常为1位、1.5位、2位)。停止位必须为逻辑 1。在一次串口通信过程中,数据接收与发送双方…

[STM32]定位器与PWM的LED控制

目录 1. 深入了解STM32定时器原理&#xff0c;掌握脉宽调制pwm生成方法。 (1)STM32定时器原理 原理概述 STM32定时器的常见模式 使用步骤 (2)脉宽调制pwm生成方法。 2. 实验 (1)LED亮灭 代码 测试效果 (2)呼吸灯 代码 测试效果 3.总结 1. 深入了解STM32定时器原…

Redis使用中的性能优化——搭建Redis的监测服务

大纲 环境安装配置Redis安装 安装配置redis_exporter编译运行 安装启动Prometheus创建用户下载并解压修改配置启动 安装启动grafana安装启动 测试参考资料 抛开场景和数据&#xff0c;谈论性能优化&#xff0c;就是纸上谈兵。这个系列我们将通过相关数据来展现常见的Mysql优化前…

微信小程序多端框架打包后发布到APP Store

IPA 上架 App Store 生成 iOS 证书和 Provisioning Profile iOS 开发者账号缴/续费的发票查看和获取 个人开发者把小程序发布到 App Store 5个步骤&#xff08;保姆级教程&#xff09; 一、参数的设置、证书的生成、生成profile文件 微信小程序多端应用Donut IOS相关的参数…

互联网轻量级框架整合之SpringMVC初始化及各组件工作原理

Spring MVC的初始化和流程 MVC理念的发展 SpringMVC是Spring提供给Web应用领域的框架设计&#xff0c;MVC分别是Model-View-Controller的缩写&#xff0c;它是一个设计理念&#xff0c;不仅仅存在于Java中&#xff0c;各类语言及开发均可用&#xff0c;其运转流程和各组件的应…

使用Ollama+OpenWebUI部署和使用Phi-3微软AI大模型完整指南

&#x1f3e1;作者主页&#xff1a; 点击&#xff01; &#x1f916;AI大模型部署与应用专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年6月6日23点50分 &#x1f004;️文章质量&#xff1a;96分 欢迎来到Phi-3模型的奇妙世界&#xff01;Phi-3是由微软…

网络安全:https劫持

文章目录 参考https原理https窃听手段SSL/TLS降级原理难点缺点 SSL剥离原理发展缺点前端劫持 MITM攻击透明代理劫持 参考 https原理 SNI 浏览器校验SSL证书 https降级 https握手抓包解析 lets encrypt申请证书 https原理 步骤如下&#xff1a; 客户端向服务器发送https请求。…

动态IP与静态IP的优缺点

在网络连接中&#xff0c;使用动态和静态 IP 地址取决于连接的性质和要求。静态 IP 地址通常更适合企业相关服务&#xff0c;而动态 IP 地址更适合家庭网络。让我们来看看动态 IP 与静态 IP 的优缺点。 1.静态IP的优点&#xff1a; 更好的 DNS 支持&#xff1a;静态 IP 地址在…

MATLAB基础应用精讲-【数模应用】二元Logit分析(最终篇)(附python、MATLAB和R语言代码实现)

目录 算法原理 SPSSAU 1、二元logistic分析思路说明 2、如何使用SPSSAU进行二元logistic操作 3、二元logistic相关问题 算法流程 一、分析前准备 1、确定分析项 2.多重共线性判断 3.数据预处理 二、回归基本情况分析 三、模型拟合评价 1、似然比检验 2、拟合优…

晶圆几何量测系统支持半导体制造工艺量测,保障晶圆制造工艺质量

晶圆面型参数厚度、TTV、BOW、Warp、表面粗糙度、膜厚、等是芯片制造工艺必须考虑的几何形貌参数。其中TTV、BOW、Warp三个参数反映了半导体晶圆的平面度和厚度均匀性&#xff0c;对于芯片制造过程中的多个关键工艺质量有直接影响。 TTV、BOW、WARP对晶圆制造工艺的影响 对…

详细分析Mysql中的 JSON_ARRAYAGG 基本知识(附Demo)

目录 1. 基本知识2. Demo2.1 简单聚合2.2 带排序聚合2.2.1 子查询进行排序2.2.2 创建临时表 2.3 带条件聚合2.4 多列聚合2.5 嵌套 JSON 结构 1. 基本知识 JSON_ARRAYAGG为 SQL 聚合函数&#xff0c;用于将一组值聚合为一个 JSON 数组 多行结果组合成一个 JSON 数组形式的场景…

企业研发数据泄露损失严重,研发数据保护到底怎么才能有效落地?

数据已成为企业毋庸置疑的核心资产&#xff0c;而企业众多数据中&#xff0c;研发数据则占据着重要的角色&#xff0c;近年来&#xff0c;发生了多起企业研发数据被窃取或泄露的事件&#xff0c;给企业带来严重的名誉、经济损失&#xff1a; 小米公司&#xff1a;2023年1月&am…