每日一题——Python实现PAT甲级1112 Stucked Keyboard(举一反三+思想解读+逐步优化)五千字好文


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

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

Python-3.12.0文档解读

目录

 我的写法

时间复杂度

空间复杂度

总结

我要更强

代码分析

时间复杂度

空间复杂度

哲学和编程思想

抽象与具体化:

效率与优化:

数据结构与算法:

迭代与递归:

模块化与可维护性:

预处理与后处理:

单一职责原则:

测试与验证:

举一反三

1. 抽象与具体化

2. 效率与优化

3. 数据结构与算法

4. 迭代与递归

5. 模块化与可维护性

6. 预处理与后处理

7. 单一职责原则

8. 测试与验证

综合应用


题目链接

 我的写法

# 读取输入的整数 k
k = int(input())# 读取输入的字符串 resulting_str
resulting_str = input()# 初始化一个空集合,用于存储去重后的字符
resulting_str_set = set()# 初始化一个空集合,用于存储卡住的键
stucked_keys = set()# 遍历字符串中的每一个字符
for char in resulting_str:# 如果字符不在集合 resulting_str_set 中if char not in resulting_str_set:# 将字符添加到集合 resulting_str_set 中resulting_str_set.add(char)# 检查字符在字符串中出现的次数是否是 k 的整数倍if resulting_str.count(char * k) * k == resulting_str.count(char):# 如果是的话,说明这个字符是卡住键,将其添加到 stucked_keys 集合中stucked_keys.add(char)# 打印卡住的键,不换行print(char, end='')# 打印一个换行符
print()# 遍历所有卡住的键
for char in stucked_keys:# 将原字符串中所有连续 k 次出现的卡住键替换为单个字符resulting_str = resulting_str.replace(char * k, char)# 输出处理后的字符串
print(resulting_str)

这段代码的功能是从输入的字符串中识别出“卡住”的键,并在输出中将这些卡住的键只显示一次,同时还会恢复原始字符串中这些卡住键的正确形式。下面是对代码的专业点评以及复杂度分析:

  1. 输入处理:
  2. 集合初始化:
  3. 遍历字符并检查卡住键:
    • 通过 if char not in resulting_str_set 确保每个字符只处理一次,避免重复计算。
    • resulting_str.count(char * k) 计算子串 char * k 在 resulting_str 中的出现次数,但这部分的计算效率不高,因为 count 方法的时间复杂度为 (O(n))。
    • resulting_str.count(char * k) * k == resulting_str.count(char) 检查字符出现次数是否为 k 的整数倍。如果是,则该字符认为是卡住键。
  4. 替换卡住键的子串:
    • 遍历卡住键集合,并将字符串中连续 k 次出现的卡住键替换为单个字符。
  5. 输出结果:

时间复杂度

  1. 字符遍历:遍历字符串的每一个字符,时间复杂度为 (O(n)),其中 (n) 是字符串的长度。
  2. 字符计数:resulting_str.count(char * k) 的时间复杂度为 (O(n)),这个操作在最坏情况下需要对每个字符进行一次,总的时间复杂度为 (O(n^2))。
  3. 替换操作:替换的时间复杂度为 (O(n)),因为 replace 方法需要遍历整个字符串。

综合来看,最坏情况下的时间复杂度为 (O(n^2))。

空间复杂度

  1. 集合存储:两个集合 resulting_str_set 和 stucked_keys 最多存储 n 个字符,所以空间复杂度为 (O(n))。
  2. 字符串存储:输入字符串和处理后的字符串都需要占用 (O(n)) 的空间。

综合来看,空间复杂度为 (O(n))。

总结

这段代码实现了预期的功能,但在字符计数部分的效率较低,导致最坏情况下的时间复杂度为 (O(n^2))。可以通过更高效的算法(例如滑动窗口或预处理字符频率)来优化计算字符重复出现的次数,从而降低总体时间复杂度。总体而言,代码逻辑清晰,结构合理,但在处理大规模输入时性能可能受限。


我要更强

为了优化这段代码,可以采取以下方法:

  1. 优化计数操作:我们可以通过一次遍历来记录每个字符的出现位置和出现次数,这样可以避免多次使用 count 函数。
  2. 使用哈希表:用字典代替集合来存储字符的频率及其索引信息,可以在一次遍历中完成所有统计和检查操作。

下面是优化后的代码,时间复杂度从 (O(n^2)) 降低到 (O(n)),空间复杂度仍为 (O(n))。

# 读取输入的整数 k
k = int(input())# 读取输入的字符串 resulting_str
resulting_str = input()# 初始化一个字典用于存储字符的频率
char_count = {}# 遍历字符串,统计字符频率
for i, char in enumerate(resulting_str):if char not in char_count:char_count[char] = []char_count[char].append(i)# 初始化一个集合,用于存储卡住的键
stucked_keys = set()# 检查每个字符的频率是否符合卡住键的条件
for char, indices in char_count.items():if len(indices) % k == 0:# 符合卡住键条件stucked_keys.add(char)# 输出卡住的键,不换行print(char, end='')print()# 构建一个新的字符串,用于替换卡住键
resulting_list = list(resulting_str)
for char in stucked_keys:i = 0while i < len(resulting_list):# 找到连续 k 个相同字符的位置if resulting_list[i:i + k] == [char] * k:# 替换为单个字符resulting_list[i:i + k] = [char]i += kelse:i += 1# 将列表转换为字符串并输出
resulting_str = ''.join(resulting_list)
print(resulting_str)

代码分析

  1. 输入处理:
  2. 字符频率统计:
    • 这里使用字典 char_count 记录每个字符出现的索引位置。
  3. 卡住键检查和输出:
    • 检查每个字符的出现次数是否是 k 的整数倍,符合条件的字符加入 stucked_keys 集合,并输出。
  4. 构建新字符串:
  • 使用列表 resulting_list 来构建新的字符串,逐段检查并替换连续 k 个相同字符。

时间复杂度

  1. 字符频率统计:遍历字符串一次,时间复杂度为 (O(n))。
  2. 卡住键检查:检查每个字符的频率,最坏情况下时间复杂度为 (O(n))。
  3. 构建新字符串:遍历列表进行替换,时间复杂度为 (O(n))。

综合来看,优化后的时间复杂度为 (O(n))。

空间复杂度

  1. 字符频率统计:字典 char_count 需要存储每个字符的索引,空间复杂度为 (O(n))。
  2. 结果存储:列表 resulting_list 需要与输入字符串相同的空间,空间复杂度为 (O(n))。

综合来看,空间复杂度为 (O(n))。

通过这些优化,代码在时间复杂度和空间复杂度方面已经有了显著改进。


哲学和编程思想

优化这段代码的过程中,涉及到了多种哲学和编程思想,具体包括:

  1. 抽象与具体化:

    • 在编程中,抽象是指忽略或隐藏细节,专注于问题的本质特征。具体化则是将抽象的概念转化为具体的实现。在这个优化过程中,我们抽象出了“卡住键”的概念,并通过具体化的代码实现来处理这些键。
  2. 效率与优化:

    • 编程中的效率哲学强调在解决问题时尽可能减少资源消耗(如时间、空间)。通过优化计数操作和使用更高效的数据结构(如哈希表),我们减少了时间复杂度,体现了效率哲学。
  3. 数据结构与算法:

    • 选择合适的数据结构和算法是编程中的核心思想。在这个例子中,我们使用了字典(哈希表)来存储字符的频率和位置,这是一种高效的数据结构,可以快速查找和更新数据。
  4. 迭代与递归:

    • 迭代是通过循环重复执行一系列操作,而递归是通过函数调用自身来解决问题。在这个优化中,我们使用了迭代(遍历字符串)来处理问题,而不是递归,因为迭代通常在时间和空间上更高效。
  5. 模块化与可维护性:

    • 模块化编程思想强调将程序分解为独立、可替换的模块,每个模块具有单一功能。这种思想有助于提高代码的可读性和可维护性。在这个代码中,我们通过将不同的功能(如输入处理、频率统计、卡住键检查)分离到不同的代码块中,实现了模块化。
  6. 预处理与后处理:

    • 预处理是在处理主要问题之前对数据进行准备,后处理是在处理主要问题之后对结果进行整理。在这个例子中,我们预先统计了字符的频率和位置,这是预处理;在处理完卡住键后,我们构建了新的字符串,这是后处理。
  7. 单一职责原则:

    • 这个原则要求一个模块或函数应该只有一个引起它变化的原因。在优化后的代码中,每个函数或代码块都专注于一个特定的任务,如统计字符频率、检查卡住键、构建新字符串等。
  8. 测试与验证:

  • 在编程中,测试和验证是确保代码正确性的重要环节。虽然在这个讨论中没有展示具体的测试代码,但在实际开发中,编写测试用例来验证代码的功能是不可或缺的。

通过这些哲学和编程思想的指导,能够更有效地解决问题,提高代码的质量和性能。


举一反三

1. 抽象与具体化

技巧:

  • 找出共性:在解决问题之前,先找出问题中各个部分的共性,进行抽象化。这样可以减少重复工作。
  • 分而治之:将大问题分解成若干个子问题,逐个解决。每个子问题可以更容易抽象和具体化。

举例:给定一组操作(如插入、删除、查找),抽象出一个通用的数据结构接口,然后具体化为不同的数据结构(如数组、链表、哈希表)。

2. 效率与优化

技巧:

  • 选择合适的数据结构:根据操作的频率和类型(如查找、插入、删除)选择最合适的数据结构。
  • 减少冗余计算:避免重复计算,通过缓存(如动态规划中的记忆化)来提高效率。
  • 使用空间换时间:在某些情况下,通过增加一些额外的存储空间可以显著提高时间效率。

举例:在动态规划中,通过保存子问题的解来避免重复计算,从而降低时间复杂度。

3. 数据结构与算法

技巧:

  • 熟悉常用数据结构:如数组、链表、栈、队列、树、图、哈希表等,了解它们的特性和适用场景。
  • 掌握经典算法:如排序、搜索、动态规划、贪心算法、回溯等,理解它们的实现和优化。

举例:对于频繁查找操作,优先考虑使用哈希表或二分搜索树。

4. 迭代与递归

技巧:

  • 优先选择迭代:在大多数情况下,迭代比递归更高效且更容易控制栈空间。
  • 优化递归:如果必须使用递归,考虑使用尾递归或将递归转换为迭代。

举例:斐波那契数列的计算可以使用迭代替代递归,从而避免栈溢出。

5. 模块化与可维护性

技巧:

  • 单一职责:每个函数和模块应该只做一件事,这样可以提高代码的可读性和可维护性。
  • 松耦合:模块之间的依赖关系应该尽量简单,减少耦合度,使得更容易进行修改和维护。

举例:将输入处理、数据处理、输出结果分成不同的函数或模块。

6. 预处理与后处理

技巧:

  • 提前准备:在主算法运行前,进行必要的数据预处理,可以显著提高整体效率。
  • 整理结果:在主算法运行后,对结果进行格式化或整理,使其更易于使用和理解。

举例:在字符串匹配问题中,预先构建一个模式表来加速匹配过程。

7. 单一职责原则

技巧:

  • 功能分离:确保每个函数或模块只负责一个功能,尽量避免“大而全”的函数。
  • 明确接口:定义清晰的接口,使得模块之间的交互简单明了。

举例:一个计算器程序,应该将输入解析、运算处理、结果输出分成不同的模块。

8. 测试与验证

技巧:

  • 全面测试:编写覆盖各种边界情况和特殊情况的测试用例,确保代码的健壮性。
  • 自动化测试:使用单元测试框架(如JUnit、pytest)来自动化测试过程,提高效率。

举例:对于每个函数,编写一组测试用例,包括正常输入、边界输入和异常输入。

综合应用

综合技巧:

  • 问题分解:将复杂的问题分解成多个小问题,通过组合这些小问题的解来解决整体问题。
  • 多角度思考:从不同的角度(如时间复杂度、空间复杂度、代码可维护性)来思考和优化代码。
  • 不断学习:保持对新技术、新算法的学习热情,丰富自己的工具箱。

举例:在面对一个新的编程挑战时,可以先尝试简单的暴力解法,然后通过优化数据结构和算法来逐步提升性能。

通过这些技巧和思路,不仅可以提高解决当前问题的效率,还能在面对新问题时举一反三,找到更加高效和优雅的解决方案。


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

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

相关文章

组织创新|AI赋能敏捷实践,助力企业敏捷转型

在工业5.0时代&#xff0c;随着项目变得越来越复杂&#xff0c;对效率的需求也在增长&#xff0c;致力于敏捷转型的组织正在寻求创新的解决方案来应对常见的挑战&#xff1a;工作量不平衡、低效的任务分配和知识孤岛等等。对此&#xff0c;AI等尖端技术的潜力可以帮助实现更高效…

测试多模态模型MiniCPM

目录 模型参考信息&#xff1a; 文件目录&#xff1a; 使用图片&#xff1a; 执行结果&#xff1a; 让模型用中文输出&#xff1a; 评价 模型参考信息&#xff1a; https://huggingface.co/openbmb/MiniCPM-Llama3-V-2_5 文件目录&#xff1a; 使用图片&#xff1a; h…

HCIA14 DHCP 实验

动态主机配置协议 DHCP&#xff08;Dynamic Host Configuration Protocol&#xff09;由 RFC 2131 定义&#xff0c;采用客户端/服务器通信模式&#xff0c;由客户端&#xff08;DHCP Client&#xff09;向服务器&#xff08;DHCP Server&#xff09;提出配置申请&#xff0c;服…

HTML--给网站添加已运行时间的统计

原文网址&#xff1a;HTML--给网站添加已运行时间的统计_IT利刃出鞘的博客-CSDN博客 简介 本文介绍怎么给自己网站添加已经运行了多长时间。 代码 <html lang"cn"><head><meta http-equiv"Content-Type" content"text/html;charse…

KafkaQ - 好用的 Kafka Linux 命令行可视化工具

鉴于并没有在网上找到比较好的linux平台的kafka可视化工具&#xff0c;今天为大家介绍一下自己开发的在 Linux 平台上使用的可视化工具KafkaQ 虽然简陋&#xff0c;主要可以实现下面的这些功能&#xff1a; 1&#xff09;查看当前topic的分片数量和副本数量 2&#xff09;查…

【GlobalMapper】去除数据黑边

tif数据加载出来有这种黑色的边框&#xff0c;使用 Global Mapper切片之后&#xff0c;会有那种黑色的色块加载出来 影像黑边出现的原因&#xff1a; 通常&#xff0c;由于影像格式、像素深度、无效值、背景值等原因&#xff0c;会产生黑边或者白边&#xff0c;给影像的拼接或…

【图书推荐】《Vue.js 3.x+Element Plus前端开发实战》

本书重点 Element Plus是一套采用Vue.js 3.x实现的UI组件库&#xff0c;它为开发者、设计师和产品经理提供了配套设计资源&#xff0c;可以帮助网站快速成型。 本书详解Vue.js 3.x和Element Plus开发方法&#xff0c;配套源码、PPT课件。 内容简介 本书分为两篇&#xff0c…

d3dcompiler_43.dll是什么文件?怎么高效率的解决d3dcompiler_43.dll丢失问题

d3dcompiler_43.dll是什么文件&#xff1f;当你知道d3dcompiler_43.dll这个文件名字的时候&#xff0c;相信你是遇到了d3dcompiler_43.dll丢失的问题了&#xff01;所以才会这样问&#xff0c;其实这就是一个普通的dll文件&#xff0c;对于电脑系统有着至关重要的作用&#xff…

干货分享:宏集物联网HMI通过S7 MPI协议采集西门子400PLC数据

前言 为了实现和西门子PLC的数据交互&#xff0c;宏集物联网HMI集成了S7 PPI、S7 MPI、S7 Optimized、S7 ETH等多个驱动来适配西门子200、300、400、1200、1500、LOGO等系列PLC。 本文主要介绍宏集HMI通过S7 MPI协议采集西门子400PLC数据的操作步骤&#xff0c;其他协议的操作…

【面经总结】Java基础 - IO

序列化 什么是序列化和反序列化&#xff1f; 序列化&#xff1a;将对象转换为二进制数据 反序列化&#xff1a;将二进制数据转换为对象 目的&#xff1a;方便网络传输、持久化保存 Java 是怎么实现序列化的&#xff1f; Java 通过对象输入输出流来实现序列化和反序列化&a…

tp6+swoole+mysql+nginx+redis高并发优化

1.服务器 IDC机房提供的物理机&#xff1a;单机 40核&#xff0c;64G内存&#xff0c;带宽100M&#xff0c; 2.redis 7.2配置 timeout600 #空闲连接超时时间,0表示不断开 maxclients100000 #最大连接数 3.Mysql 5.7配置&#xff0c;按宝塔16-32G优化方案并调整&#xff1a;…

通用大模型VS垂直大模型,相辅相成!

1.通用大模型&#xff1a; 如OpenAI的GPT系列、Google的PaLM等&#xff0c;因其广泛的训练数据来源和强大的泛化能力&#xff0c;展现出在多种任务和场景中的应用潜力。它们能够处理从文本生成、代码编写到语言翻译等多种复杂任务&#xff0c;适应性强&#xff0c;减少了针对单…

第二届京津冀现代商贸物流金融创新发展百人大会将于6月16日在廊坊举行

编辑&#xff5c;Ray 物流是实体经济的“筋络”&#xff0c;联接生产和消费、内贸和外贸&#xff0c;必须有效降低全社会物流成本&#xff0c;增强产业核心竞争力&#xff0c;提高经济运行效率。《京津冀协同发展规划纲要》赋予河北“三区一基地”的功能定位&#xff0c;建设全…

第十七章 策略模式

目录 1 策略模式概述 2 策略模式原理 3 策略模式实现 4 策略模式应用实例 5 策略模式总结 1 策略模式概述 策略模式(strategy pattern)的原始定义是&#xff1a;定义一系列算法&#xff0c;将每一个算法封装起来&#xff0c;并使它们可以相互替换。策略模式让算法可以独立…

java实现文件的压缩及解压

一、起因 开发中需要实现文件的压缩及解压功能&#xff0c;以满足某些特定场景的下的需要&#xff0c;在此说下具体实现。 二、实现 1.定义一个工具类ZipUtils,实现文件的压缩及解压&#xff0c;代码如下&#xff1a; import java.io.*; import java.nio.charset.Charset; impo…

TCPListen客户端和TCPListen服务器

创建项目 TCPListen服务器 public Form1() {InitializeComponent();//TcpListener 搭建tcp服务器的类&#xff0c;基于socket套接字通信的//1创建服务器对象TcpListener server new TcpListener(IPAddress.Parse("192.168.107.83"), 3000);//2 开启服务器 设置最大…

据阿谱尔统计显示,2023年全球凹版印刷机市场销售额约为9.1亿美元

根据阿谱尔 (APO Research&#xff09;的统计及预测&#xff0c;2023年全球凹版印刷机市场销售额约为9.1亿美元&#xff0c;预计在2024-2030年预测期内将以超过2.54%的CAGR&#xff08;年复合增长率&#xff09;增长。 由于对软包装和印刷包装的需求不断增长&#xff0c;全球凹…

数据分析-Excel基础函数的使用

Excel基础函数&#xff1a; sum:求和 sumif:单条件求和 sumifs:多条件求和 subtotal:根据筛选求和 if:逻辑判断 vlookup:连接匹配数据 match:查找数值在区域中的位置 index:根据区域的位置返回数值 match、index:一起使用&#xff1a;自动根据列名查找数据 sumifs、match、ind…

2.线性神经网络

目录 1.线性回归一个简化模型线性模型&#xff1a;可以看做是单层神经网络衡量预估质量训练数据参数学习显示解总结 2.基础优化方法小批量随机梯度下降总结 3.Softmax回归&#xff1a;其实是一个分类问题回归VS分类从回归到多类分类---均方损失Softmax和交叉熵损失 4.损失函数L…

web前端:作业三

1.回到顶部案例(固定定位) <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style>#container{height: 5000px;border: 1px solid blue;}#back-button{width: 100px;height: 100px;border: 1px solid…