当前位置: 首页 > news >正文

每日一题——Python实现PAT乙级1030 完美数列(举一反三+思想解读+逐步优化)五千字好文


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

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

Python-3.12.0文档解读

目录

初次尝试

再次尝试

代码结构

时间复杂度分析

空间复杂度分析

总结

我要更强

时间复杂度分析

空间复杂度分析

总结

哲学和编程思想

抽象与模块化:

效率与性能优化:

数据结构的选择:

迭代与递增开发:

避免重复计算:

错误处理与容错:

代码可读性与维护性:

测试与验证:

举一反三

理解问题本质:

选择合适的数据结构:

优化算法:

模块化设计:

迭代开发:

代码复用:

编写清晰的代码:

测试驱动开发:

持续学习和实践:

反思和总结:


题目链接:https://pintia.cn/problem-sets/994805260223102976/exam/problems/type/7?problemSetProblemId=994805291311284224&page=0

初次尝试

import sys  # 导入sys模块,用于读取标准输入# 使用sys.stdin.read方法读取所有输入,并将其分割成一个列表
input = sys.stdin.read
inputs = input().split()# 从输入列表中提取N和p的值
N = int(inputs[0])
p = int(inputs[1])# 将输入列表中剩余的部分转换为整数列表
nums = list(map(int, inputs[2:]))# 初始化目标数列列表
target_nums = list()# 初始化最大值M和最小值m为数列的第一个元素
M = nums[0]
m = nums[0]# 遍历输入的数列
for i in range(N):# 将当前元素添加到目标数列中target_nums.append(nums[i])# 保存上一次的最大值和最小值last_M = Mlast_m = m# 标记是否有最大值或最小值被改变M_or_m_changed = -1# 如果当前元素大于或等于M,则更新Mif M <= nums[i]:M = nums[i]M_or_m_changed = 1# 如果当前元素小于或等于m,则更新melif nums[i] <= m:m = nums[i]M_or_m_changed = 0# 检查当前目标数列是否满足完美数列的条件if M <= m * p:pass  # 如果满足条件,则不做任何操作else:# 如果不满足条件,则从目标数列中移除最后一个元素target_nums.pop()# 根据是否有最大值或最小值被改变,恢复它们if M_or_m_changed == 1:M = last_Melif M_or_m_changed == 0:m = last_m# 输出目标数列的长度
sys.stdout.write(f"{len(target_nums)}\n")

再次尝试

import sys# 读取输入
input = sys.stdin.read
inputs = input().split()
N = int(inputs[0])
p = int(inputs[1])
nums = list(map(int, inputs[2:]))# 对数列进行排序
nums.sort()# 初始化双指针和最大长度
left = 0
max_length = 0# 使用双指针遍历数列
for right in range(N):# 移动左指针,直到子数组满足条件while nums[right] > nums[left] * p:left += 1# 更新最大长度max_length = max(max_length, right - left + 1)# 输出结果
sys.stdout.write(f"{max_length}\n")

这段代码实现了一个双指针算法,用于解决一个特定问题:给定一个数列和乘数p,找到数列中满足任意元素大于其左边任意元素乘以p的最长子数组的长度。下面是对这段代码的点评:

代码结构

  1. 输入处理

    • 使用sys.stdin.read读取所有输入,并将输入分割成整数。
    • 读取数列长度N、乘数p和数列本身。
  2. 排序

    • 对数列进行排序,这是为了后续的双指针算法能够正确工作。
  3. 双指针算法

    • 初始化左指针left和最大长度max_length
    • 遍历数列,使用右指针right
    • 当右指针指向的元素大于左指针指向的元素乘以p时,移动左指针。
    • 每次移动右指针后,更新最大长度。
  4. 输出结果

    • 使用sys.stdout.write输出最大长度。

时间复杂度分析

  • 排序:使用Python内置的sort()方法,时间复杂度为O(N log N),其中N是数列的长度。
  • 双指针遍历:每个元素最多被访问两次(一次由左指针,一次由右指针),因此这一部分的时间复杂度是O(N)。
  • 总时间复杂度为O(N log N + N),由于N log N在渐近意义上占主导,所以整体时间复杂度为O(N log N)。

空间复杂度分析

  • 输入处理:存储输入的数列需要O(N)的空间。
  • 排序:Python的sort()方法在原地排序,不需要额外空间。
  • 双指针算法:只需要常数级别的额外空间。
  • 总空间复杂度为O(N)。

总结

这段代码有效地使用了双指针算法来解决问题,通过排序简化了问题的处理。时间复杂度主要受排序影响,而空间复杂度相对较低。代码结构清晰,逻辑明确,是一个良好的算法实现。


我要更强

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

  1. 避免排序:排序的时间复杂度是O(N log N),如果我们能够避免排序,可以显著减少时间复杂度。
  2. 使用更高效的数据结构:例如,使用哈希表来存储和快速查找元素。
  3. 优化双指针算法:确保算法的每个步骤都是必要的,避免不必要的计算。

下面是一个优化后的代码实现,避免了排序,并使用了哈希表来存储元素和它们的位置:

import sys# 读取输入
input = sys.stdin.read
inputs = input().split()
N = int(inputs[0])
p = int(inputs[1])
nums = list(map(int, inputs[2:]))# 使用哈希表存储数列元素和它们的位置
num_positions = {num: i for i, num in enumerate(nums)}# 初始化双指针和最大长度
left = 0
max_length = 0# 使用双指针遍历数列
for right in range(N):# 移动左指针,直到子数组满足条件while nums[right] > nums[left] * p:left += 1# 更新最大长度max_length = max(max_length, right - left + 1)# 输出结果
sys.stdout.write(f"{max_length}\n")

时间复杂度分析

  • 输入处理:时间复杂度为O(N),因为我们遍历了一次输入来创建数组和哈希表。
  • 双指针遍历:时间复杂度为O(N),因为每个元素最多被访问两次。
  • 总时间复杂度为O(N),这是一个显著的改进,因为我们避免了排序。

空间复杂度分析

  • 输入处理:空间复杂度为O(N),因为我们存储了数组和哈希表。
  • 双指针算法:只需要常数级别的额外空间。
  • 总空间复杂度为O(N)。

总结

这个优化版本的代码通过避免排序和使用哈希表来存储元素位置,将时间复杂度从O(N log N)降低到O(N),同时保持了空间复杂度为O(N)。这是一个更高效的解决方案,特别是在处理大规模数据时。


哲学和编程思想

优化算法的过程中,运用了多种哲学和编程思想,以下是一些关键点:

  1. 抽象与模块化

    • 在编程时,我们将问题分解为更小的、可管理的部分(如输入处理、数据结构创建、算法实现等),每个部分都有明确的功能和接口。这种模块化的方法使得代码更易于理解和维护。
  2. 效率与性能优化

    • 我们关注算法的时间复杂度和空间复杂度,通过避免不必要的排序操作和使用哈希表来提高效率。这种优化体现了对算法性能的重视,是计算机科学中追求高效计算的核心思想。
  3. 数据结构的选择

    • 使用哈希表来存储元素和它们的位置,这是基于对数据结构特性的理解。哈希表提供了快速的查找操作,非常适合需要频繁查找元素位置的场景。
  4. 迭代与递增开发

    • 在实现算法时,我们采用迭代的方法,逐步构建和测试代码。这种方法有助于及时发现和修复问题,同时也使得代码的开发过程更加稳健。
  5. 避免重复计算

    • 通过预先存储元素位置,我们避免了在双指针算法中重复查找元素位置的操作。这种避免重复计算的思想是优化算法性能的重要策略。
  6. 错误处理与容错

    • 虽然代码中没有显式的错误处理,但在实际应用中,考虑输入的合法性和异常情况的处理是重要的。这体现了编程中的容错思想,即确保程序在面对不完美或异常输入时仍能稳定运行。
  7. 代码可读性与维护性

    • 代码中使用了清晰的变量命名和适当的注释,这有助于提高代码的可读性。良好的代码风格和结构使得代码更易于维护和扩展。
  8. 测试与验证

    • 在实际应用中,对算法进行充分的测试是确保其正确性和性能的关键。这包括单元测试、集成测试等,确保代码在各种情况下都能按预期工作。

通过这些哲学和编程思想的应用,不仅提高了算法的效率,也确保了代码的质量和可维护性。这些原则是软件工程和算法设计中的基础,对于开发高效、可靠的软件系统至关重要。


举一反三

根据上述哲学和编程思想,以下是一些技巧和策略,可以帮助你在面对类似问题时举一反三:

  1. 理解问题本质

    • 在开始解决问题之前,深入理解问题的本质和需求。这有助于确定最合适的算法和数据结构。
  2. 选择合适的数据结构

    • 根据问题的特性选择最合适的数据结构。例如,如果需要快速查找和插入操作,哈希表可能是一个好选择;如果需要保持元素的顺序,链表或数组可能更合适。
  3. 优化算法

    • 分析算法的时间复杂度和空间复杂度,寻找可能的优化点。例如,通过避免重复计算、使用缓存或减少不必要的操作来提高效率。
  4. 模块化设计

    • 将问题分解为更小的模块,每个模块负责一个特定的功能。这不仅使代码更易于管理,也便于测试和维护。
  5. 迭代开发

    • 采用迭代的方法开发代码,逐步增加功能并进行测试。这种方法有助于及时发现问题并进行调整。
  6. 代码复用

    • 尽可能复用已有的代码和解决方案。这不仅可以节省时间,也有助于保持代码的一致性和质量。
  7. 编写清晰的代码

    • 使用有意义的变量名、注释和清晰的代码结构。这有助于他人(或未来的你)理解和维护代码。
  8. 测试驱动开发

    • 在编写代码之前先编写测试用例。这有助于确保代码的正确性,并鼓励开发出更健壮的解决方案。
  9. 持续学习和实践

    • 不断学习新的编程技术和算法,通过实践应用这些知识。这有助于提高解决问题的能力。
  10. 反思和总结

    • 在解决问题后,回顾整个过程,总结哪些方法有效,哪些可以改进。这种反思有助于在未来的问题解决中更加高效。

通过应用这些技巧和策略,不仅能够解决当前的问题,还能够提高自己解决更广泛问题的能力。记住,编程和算法设计是一个不断学习和实践的过程,持续的努力和反思将使你成为一个更优秀的程序员。


相关文章:

每日一题——Python实现PAT乙级1030 完美数列(举一反三+思想解读+逐步优化)五千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 初次尝试 再次尝试 代码结构 时间复杂度分析 空间复杂度分析 总结 我要更强 时…...

【C/C++】this指针的概念和作用

目录 一、this指针的概念 二、this指针的作用 2.1 访问当前对象的成员 2.2 返回对象本身 2.3 区分对象 2.4 在构造函数和析构函数中 2.5 在类的内部调用其他成员函数 2.6 作为参数传递 三、this指针使用 3.1 this指针的使用 3.2 C++ 中this指针使用 一、this…...

Spring Bean 的生命周期

在 Spring 框架中&#xff0c;Bean 的生命周期由 Spring 容器管理&#xff0c;从创建到销毁&#xff0c;Spring 提供了多种方式来定制 Bean 的初始化和销毁过程。本文将详细介绍 Spring Bean 的生命周期&#xff0c;包括 Bean 的初始化和销毁、自定义初始化方法和销毁方法。 一…...

锐起RDV5高性能云桌面

锐起是上海锐起信息技术有限公司旗下品牌。该公司创立于 2001 年&#xff0c;是桌面虚拟化产品和解决方案提供商&#xff0c;专注于桌面管理系统和私有云存储系统的系列软件产品研发&#xff0c;致力于简化 IT 管理、增强系统安全&#xff0c;提供简单、易用、稳定、安全的产品…...

pandas减少dataframe占用内存的若干方法

一、只获取文件需要的列&#xff0c;避免加载整个文件 举例&#xff1a;只获取A.B两列数据 df pd.read_csv(123.csv, usecols[A, B]) 二、使用更准确的数据类型&#xff0c;减少内存空间占用 import pandas as pd import numpy as np # 假设你的CSV文件有三列&#xff0…...

Ubuntu20.04 64位 安装docker(有问题可评论沟通交流)

1、查看系统版本 cat /proc/version 2、卸载可能存在或未安装成功的docker&#xff08;新系统无需操作&#xff09; apt-get remove docker docker-engine docker-ce docker.io 3、更新apt-get apt-get update 4、安装软件包允许apt-get通过 HTTPS 使用存储库 apt-get install …...

【C++PCL】点云处理Kd树和八叉树区别

作者:迅卓科技 简介:本人从事过多项点云项目,并且负责的项目均已得到好评! 公众号:迅卓科技,一个可以让您可以学习点云的好地方 重点:每个模块都有参数如何调试的讲解,即调试某个参数对结果的影响是什么,大家有问题可以评论哈,如果文章有错误的地方,欢迎来指出错误的…...

makefile学习过程

makefile 完美教程 - WittXie - 博客园 (cnblogs.com) Makefile教程&#xff08;绝对经典&#xff0c;所有问题看这一篇足够了&#xff09;-CSDN博客 Makefile入门(超详细一文读懂)-CSDN博客 最实用的Makefile教程 真的很简单&#xff08;搞不明白网上的教程写那么复杂干嘛&…...

Kompas AI数据分析与预测功能对比

一、引言 在现代商业环境中&#xff0c;数据分析与预测是企业制定战略决策的关键工具。通过对大量数据的分析&#xff0c;企业能够识别趋势、预测未来变化&#xff0c;并做出更为明智的决策。本文将对比Kompas AI与其他主要AI产品在数据分析与预测方面的能力&#xff0c;展示K…...

Appium+python自动化(二十五)- 那些让人抓耳挠腮、揪头发和掉头发的事 - 获取控件ID(超详解)

简介 在前边的第二十二篇文章里&#xff0c;已经分享了通过获取控件的坐标点来获取点击事件的所需要的点击位置&#xff0c;那么还有没有其他方法来获取控件点击事件所需要的点击位置呢&#xff1f;答案是&#xff1a;Yes&#xff01;因为在不同的大小屏幕的手机上获取控件的坐…...

【博士每天一篇文献-算法】Fearnet Brain-inspired model for incremental learning

阅读时间&#xff1a;2023-12-16 1 介绍 年份&#xff1a;2017 作者&#xff1a;Ronald Kemker&#xff0c;美国太空部队&#xff1b;Christopher Kanan&#xff0c;罗切斯特大学 期刊&#xff1a; arXiv preprint 引用量&#xff1a;520 Kemker R, Kanan C. Fearnet: Brain-…...

Appium+python自动化(二十六)- 烟花一瞬,昙花一现 -Toast提示(超详解)

简介  今天宏哥在这里首先给小伙伴们和童鞋们分享一个有关昙花的小典故&#xff1a;话说昙花原是一位花神&#xff0c;她每天都开花&#xff0c;四季都灿烂。她还爱上了每天给她浇水除草的年轻人。后来&#xff0c;此事给玉帝得知。于是&#xff0c;玉帝大发雷霆&#xff0c;要…...

大数据之路 读书笔记 Day1

大数据之路 读书笔记 Day1 阿里巴巴大数据系统体系架构图 1. 数据采集层 #mermaid-svg-YqqD2w3qV6jc2aGP {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-YqqD2w3qV6jc2aGP .error-icon{fill:#552222;}#mermaid-sv…...

吴恩达揭秘:编程Agent如何革新软件开发行业

作为 AI 领域的杰出人物&#xff0c;吴恩达教授对编程 Agent 的兴起表示了极大的兴趣。他认为&#xff0c;编程 Agent 有潜力通过自动执行繁琐的任务、提高代码质量和加速开发周期来彻底改变软件开发行业。 本文将深入探讨吴恩达对编程 Agent 的见解&#xff0c; 多代理系统质…...

Study--Oracle-04-SQL练习

一、SQL语句思维导图 二、SQL练习 -- 以employee_id 为排序&#xff0c;列出前5个人 -- FETCH select employee_id,first_name from employees order by employee_id FETCH FIRST 5 rows only; -- 以employee_id 为排序&#xff0c;从第6个人开始 到第10个人 -- offset …...

目前音质最好的麦克风是哪款,一文读懂无线麦克风推荐哪些品牌好

​在自媒体时代&#xff0c;无线领夹麦克风成为自媒体人不可或缺的助手。它帮助我们在各种环境中保持清晰声音&#xff0c;提升创作效率与作品质量。然而&#xff0c;面对众多无线麦克风产品&#xff0c;挑选一款性价比高、性能卓越的款式却成为难题。今天&#xff0c;我将分享…...

Python笔记 异常、模块与包

一、了解异常 异常的概念 什么是异常 当检测到一个错误时&#xff0c;Python解释器就无法继续执行了&#xff0c;反而出现了一些错误的提示&#xff0c;这就是所谓的“异常”&#xff0c;也就是我们常说的BUG。 二、异常的捕获 1.知道为什么要捕获异常 世界上没有完美的程…...

spark查看日志

Logger 当 Spark 任务已经提交到集群运行后&#xff0c;可以通过以下几种方式查看LoggerFactory输出的日志&#xff1a; Web 界面&#xff1a;在 Spark 任务运行时&#xff0c;可以通过访问 Spark 的 Web UI 来查看日志。通常&#xff0c;可以在浏览器中输入http://<drive…...

【LeetCode】每日一题:LRU缓存

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存 int get(int key) 如果关键字 key 存在于缓存中&#xff0c;则返回关键字的值&#xff0c;否则返回 -1 …...

记录一个Xshell使用中Xmanager...X11转发的提示问题

希望文章能给到你启发和灵感&#xff5e; 如果觉得有帮助的话&#xff0c;点赞关注收藏支持一下博主哦&#xff5e; 阅读指南 一、环境说明1.1 硬件环境1.2 软件环境 二、问题和错误三、解决四、理解和延伸一下 一、环境说明 考虑环境因素&#xff0c;大家适当的对比自己的软硬…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...