每日一题——Python实现PAT乙级1005 继续(3n+1)猜想(举一反三+思想解读+逐步优化)五千字好文


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

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

Python-3.12.0文档解读

目录

 我的写法

代码逻辑概述

时间复杂度分析

空间复杂度分析

总结

我要更强

代码优化点

时间复杂度分析

空间复杂度分析

哲学和编程思想

抽象与封装:

记忆化(Memoization):

集合操作优化:

函数式编程思想:

迭代与递归:

算法优化:

举一反三


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

 我的写法

#对任何一个正整数 n,如果它是偶数,那么把它砍掉一半;
#n//=2
#如果它是奇数,那么把 (3n+1) 砍掉一半。这样一直反复砍下去,最后一定在某一步得到 n=1。
#n=(3*n+1)//2K=int(input())nums=set(list(map(int,input().split())))
init=nums.copy()
def Callatz(num):if num%2==0:return num//2else:return (3*num+1)//2for num in init:tmp=Callatz(num)while tmp!=1:nums.discard(tmp)tmp=Callatz(tmp)print(*sorted(list(nums),reverse=True))

这段代码的核心逻辑是基于Collatz猜想,对输入的一组正整数进行迭代处理,直到所有数都变为1,并输出那些在迭代过程中没有被其他数“覆盖”的数。

代码逻辑概述

  1. 输入处理:代码首先读取一个整数K和一个整数列表,并将列表转换为集合nums,同时复制一份初始集合init。
  2. Collatz迭代:定义了一个函数Callatz,用于根据Collatz猜想的规则对数进行变换。主循环对初始集合中的每个数进行迭代,直到该数变为1。在迭代过程中,如果某个数在集合中出现,则将其移除。
  3. 输出结果:最后,代码输出剩余的数,并按降序排序。

时间复杂度分析

  • Collatz迭代:对于每个输入的数,迭代次数取决于该数的值。虽然Collatz猜想没有被证明,但实践中大多数数会在有限步骤内变为1。对于一个数n,最坏情况下的迭代次数是O(log n),因为每次迭代要么将数减半,要么将其变为3n+1并减半。
  • 集合操作:集合的discard操作时间复杂度为O(1)。

综合考虑,假设输入的数个数为K,每个数的平均值为N,则总的时间复杂度大致为O(K * log N)。

空间复杂度分析

  • 集合存储:集合nums和init存储了输入的数,空间复杂度为O(K)。
  • 其他变量:临时变量tmp和其他局部变量占用常数空间。

因此,总的空间复杂度为O(K)。

总结

这段代码实现了一个经典的数学问题,逻辑清晰,时间复杂度为O(K * log N),空间复杂度为O(K)。代码通过集合操作有效地处理了数之间的覆盖关系,并最终输出结果。


我要更强

优化时间复杂度和空间复杂度的方法主要集中在减少不必要的计算和存储。以下是几种可能的优化策略:

  1. 使用记忆化技术:将已经计算过的数及其变换记录下来,避免重复计算。
  2. 减少集合操作:在进行Collatz变换时,直接判断和移除不需要的数,避免重复操作。

下面是优化后的代码,包括详细的注释:

K = int(input())
nums = set(map(int, input().split()))
init = nums.copy()
memo = {}def Callatz(num):if num in memo:return memo[num]if num % 2 == 0:result = num // 2else:result = (3 * num + 1) // 2memo[num] = resultreturn resultfor num in init:tmp = Callatz(num)while tmp != 1:if tmp in nums:nums.discard(tmp)tmp = Callatz(tmp)print(*sorted(nums, reverse=True))

代码优化点

  1. 使用记忆化技术:
    • 新增了一个字典memo来存储已经计算过的数及其变换结果,从而避免重复计算。
    • 在Callatz函数中,首先检查数是否已经在memo中,如果在则直接返回变换结果,否则进行计算并存储在memo中。
  2. 减少集合操作:
  • 在每次进行Collatz变换时,直接判断变换后的数是否在集合nums中,如果在则移除,从而减少不必要的集合操作。

时间复杂度分析

由于使用了记忆化技术,每个数的变换结果只计算一次,因此:

  • Collatz迭代:使用记忆化技术后,每个数的最坏情况下的迭代次数仍然为O(log n),但由于避免了重复计算,整体计算次数减少。
  • 集合操作:集合的discard操作时间复杂度为O(1)。

综合考虑,优化后的时间复杂度大致为O(K * log N),和原始实现相同,但由于避免了重复计算,实际运行时间会有所减少。

空间复杂度分析

  • 集合存储:集合nums和init仍然存储了输入的数,空间复杂度为O(K)。
  • 记忆化存储:新增的字典memo在最坏情况下会存储所有经过的数,空间复杂度为O(K * log N)。

虽然引入了额外的存储空间,但总体上由于避免了重复计算,实际运行效率会更高。


哲学和编程思想

这些优化方法涉及了多个哲学和编程思想,具体包括:

  1. 抽象与封装:

    • 封装:将Collatz猜想的变换逻辑封装在Callatz函数中,使得主逻辑更加清晰和简洁。这种做法体现了面向对象编程中的封装思想,即将数据和操作数据的方法封装在一起,提高代码的可维护性和可读性。
  2. 记忆化(Memoization):

    • 动态规划:记忆化是动态规划的一种实现方式,通过存储已解决子问题的结果来避免重复计算。这种思想体现了“不要重复自己”(Don't Repeat Yourself, DRY)的原则,通过减少重复计算来提高效率。
    • 实用主义:记忆化技术体现了实用主义哲学,即在编程中注重实际效果和效率,而不是纯粹的理论或形式。
  3. 集合操作优化:

    • 最小化操作:在每次进行Collatz变换时,直接判断变换后的数是否在集合nums中,如果在则移除,从而减少不必要的集合操作。这种做法体现了“最小化操作”的思想,即在编程中尽量减少不必要的操作,以提高效率。
    • 简洁性:代码中尽量保持简洁,避免冗余操作,体现了简洁性原则,即在编程中追求简单、直接和高效的解决方案。
  4. 函数式编程思想:

    • 纯函数:Callatz函数是一个纯函数,即给定相同的输入,总是返回相同的输出,且没有副作用。这种做法符合函数式编程中的纯函数思想,提高了代码的可测试性和可维护性。
  5. 迭代与递归:

    • 迭代:代码中使用迭代(循环)来处理Collatz变换,而不是递归。迭代通常比递归更高效,因为它避免了递归调用栈的开销。这种做法体现了迭代优于递归的思想,特别是在处理大规模数据时。
  6. 算法优化:

  • 预计算:通过预先计算和存储结果,可以显著减少后续计算的时间。这种做法体现了预计算和缓存的思想,即在编程中通过预先计算和存储结果来提高效率。

总结来说,这些优化方法体现了多个编程和哲学思想,包括封装、记忆化、最小化操作、简洁性、函数式编程、迭代优于递归以及预计算和缓存等。这些思想在编程中广泛应用,旨在提高代码的效率、可维护性和可读性。


举一反三

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

  1. 抽象与封装:
    • 定义函数:将复杂或重复的逻辑封装成函数,提高代码的可读性和可维护性。
    • 模块化:将代码分解成独立的模块或类,每个模块负责一个特定的功能,便于管理和复用。
  2. 记忆化(Memoization):
    • 缓存结果:对于计算密集型或递归问题,使用字典或数组来缓存已计算的结果,避免重复计算。
    • 动态规划:对于涉及重叠子问题的问题,考虑使用动态规划来优化解决方案。
  3. 集合操作优化:
    • 减少冗余操作:在处理集合或列表时,尽量减少不必要的操作,例如使用集合的discard或remove方法来直接移除元素。
    • 使用合适的数据结构:根据问题的特点选择合适的数据结构,例如使用集合来快速查找和去重。
  4. 函数式编程思想:
    • 纯函数:尽量编写纯函数,即没有副作用且输入输出一致的函数,提高代码的可测试性和可维护性。
    • 不可变数据:尽量使用不可变数据,避免数据被意外修改,减少潜在的bug。
  5. 迭代与递归:
    • 优先迭代:在处理大规模数据时,优先考虑使用迭代而不是递归,避免栈溢出等问题。
    • 尾递归优化:如果必须使用递归,考虑使用尾递归优化,减少栈空间的使用。
  6. 算法优化:
    • 预计算:对于一些固定或可预见的结果,提前计算并存储,减少运行时的计算量。
    • 空间换时间:在时间和空间复杂度之间权衡,有时可以通过增加空间使用来减少时间复杂度。
  7. 代码简洁性:
    • 避免冗余:保持代码简洁,避免不必要的变量和操作。
    • 使用内置函数:利用Python等语言的内置函数和库,例如map、filter、sorted等,提高代码的简洁性和效率。
  8. 测试与调试:
  • 单元测试:为关键函数编写单元测试,确保其正确性。
  • 调试技巧:使用断点、日志输出等调试技巧,快速定位和修复问题。

通过掌握这些技巧,可以在面对不同问题时灵活运用,提高编程效率和代码质量。记住,编程是一个不断学习和实践的过程,不断积累经验并应用这些思想和技巧,将能够更好地解决各种编程难题。


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

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

相关文章

Nginx详解-安装配置等

目录 一、引言 1.1 代理问题 1.2 负载均衡问题 1.3 资源优化 1.4 Nginx处理 二、Nginx概述 三、Nginx的安装 3.1 安装Nginx 3.2 Nginx的配置文件 四、Nginx的反向代理【重点】 4.1 正向代理和反向代理介绍 4.2 基于Nginx实现反向代理 4.3 关于Nginx的location路径…

Jetson系列机载电脑创建热点模式配置方法

Jetson nano为例—— 创建热点模式配置方法 1.1、新建一个 WiFi 在屏幕右上角找到网络图标,点击后选择“Edit Connections”选项,进入选择网络连接页面,然后点击左下角加号,新建一个连接,类型选择 WiFi 后点击 “cre…

如何选择适合自己的巴比达内网穿透方案

选择适合自己的巴比达内网穿透方案,需要考虑几个关键因素,包括您的具体需求、安全性要求、技术水平以及预算。以下是一些选择巴比达内网穿透方案的建议步骤: 1. 确定需求和用途 首先,需要明确您希望通过内网穿透实现的具体目标和…

【linux学习---1】点亮一个LED---驱动一个GPIO

文章目录 1、原理图找对应引脚2、IO复用3、IO配置4、GPIO配置5、GPIO时钟使能6、总结 1、原理图找对应引脚 从上图 可以看出, 蜂鸣器 接到了 BEEP 上, BEEP 就是 GPIO5_IO05 2、IO复用 查找IMX6UL参考手册 和 STM32一样,如果某个 IO 要作为…

DP:解决路径问题

文章目录 二维DP模型如何解决路径问题有关路径问题的几个问题1.不同路径2.不同路径Ⅱ3.下降路径最小和4.珠宝的最高价值5.地下城游戏 总结 二维DP模型 二维动态规划(DP)模型是一种通过引入两个维度的状态和转移方程来解决复杂问题的技术。它在许多优化和…

使用VMware创建Ubuntu 24.04【一】

系列文章目录 第二章 使用Ubuntu安装Frappe-Bench【二】 文章目录 系列文章目录前言相关链接下载地址虚拟机创建与运行初始化系统中配置 前言 VMware是一个虚拟化软件,它允许用户在一台计算机上模拟多个虚拟计算机环境。通过使用VMware,用户可以轻松地…

【Python】已解决:AttributeError: ‘function’ object has no attribute ‘ELement’

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决:AttributeError: ‘function’ object has no attribute ‘ELement’ 一、分析问题背景 在Python编程中,AttributeError通常表明你试图访问一个对象…

【Linux】生物信息学常用基本命令

wget网址用于直接从网上下载某个文件到服务器,当然也可以直接从网上先把东西下到本地然后用filezilla这个软件来传输到服务器上。 当遇到不会的命令时候,可以使用man “不会的命令”来查看这个命令的详细信息。比如我想要看看ls这个命令的详细用法&…

K8S 集群节点扩容

环境说明: 主机名IP地址CPU/内存角色K8S版本Docker版本k8s231192.168.99.2312C4Gmaster1.23.1720.10.24k8s232192.168.99.2322C4Gwoker1.23.1720.10.24k8s233(需上线)192.168.99.2332C4Gwoker1.23.1720.10.24 当现有集群中的节点资源不够用&…

FFmpeg教程-三-播放pcm文件-1

目录 一,下载SDL 二,在Qt中测试 1,在pro文件中加入路径 2,在.cpp文件中加入头文件 3,进行测试 4,显示结果 一,下载SDL 通过编程的方式播放音视频,也是需要用到这2个库: FFmpeg…

2本Top,4本纯正刊,25天即录!7月刊源表已更新!

本周投稿推荐 SCI • 能源技术类,1.5-2.0(来稿即录25天) • 计算机类,2.0-3.0(纯正刊29天录用) EI • 各领域沾边均可(2天录用) CNKI • 7天录用-检索(急录友好&a…

Python处理异常用操作介绍

Python中的异常处理主要用于捕获和处理程序运行过程中出现的错误。 在编写Python程序时,我们经常会遇到各种错误,如语法错误、运行时错误等。为了确保程序的稳定性和健壮性,我们需要对可能出现的错误进行捕获和处理。本文将介绍Python中常用的…

【云原生监控】Prometheus 普罗米修斯从搭建到使用详解

目录 一、前言 二、服务监控概述 2.1 什么是微服务监控 2.2 微服务监控指标 2.3 微服务监控工具 三、Prometheus概述 3.1 Prometheus是什么 3.2 Prometheus 特点 3.3 Prometheus 架构图 3.3.1 Prometheus核心组件 3.3.2 Prometheus 工作流程 3.4 Prometheus 应用场景…

贪心算法——加工木棍(C++)

上大学,一天是一天,两天也是一天。 ——2024年6月27日 之前考试周断更了,今天重新开始! 题目描述 有n根木棍,已知每根木棍的长度和重量。这些木棍在木工机器上加工,机器准备加工木棍需要一些时间&#xf…

GraalVM

文章目录 1、什么是GraalVM2、GraalVM的两种模式1_JIT模式2_AOT模式3_总结 3、应用场景1_SpringBoot搭建GraalVM应用2_函数计算3_Serverless应用 4、参数优化和故障诊断1_内存快照文件的获取2_运行时数据的获取 1、什么是GraalVM GraalVM是Oracle官方推出的一款高性能JDK&…

【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(十九)

课程地址: 黑马程序员HarmonyOS4NEXT星河版入门到企业级实战教程,一套精通鸿蒙应用开发 (本篇笔记对应课程第 29 节) P29《28.网络连接-第三方库axios》 要想使用第三方库axios,需要先安装ohpm,因为 axios…

认识String类

文章目录 String类字符串的遍历字符串的比较字符串的替换字符串的转换字符串的切割字符串的切片字符串的查找 总结 String类 在C语言中已经涉及到字符串了,但是在C语言中要表示字符串只能使用字符数组或者字符指针,可以使用标准库提 供的字符串系列函数完…

003-GeoGebra如何无缝嵌入到PPT里

GeoGebra无缝嵌入到PPT里真是一个头疼的问题,已成功解决,这里记录一下,希望可以帮助到更多人。 注意,后续所有的文章说的PPT都是Offce Power Point, 不要拿着WPS的bug来问我哦,我已经戒WPS了(此处表示无奈&…

Mysql在Windows系统下安装以及配置

目录 一、下载Mysql 二、安装Mysql及环境配置 一、下载Mysql 1. 下载地址 官网:https://www.mysql.com,这里我选用的是Mysql8.0.37版本(版本无所谓,随便下8.0.几都行) 2.点击DOWNLOADS 然后,点击 MySQL Community…

YOLOv8目标检测在RK3588部署全过程

一,前言 这是一个关于从电脑安装深度学习环境到实现YOLOv8目标检测在RK3588上部署的全过程。 本人配置: 1,一台笔记本 2,一个香橙派5s 二,深度学习环境配置 2.1 安装anaconda 使用清华镜像源下载https://mirror…