每日一题——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.mzph.cn/news/865988.shtml

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

相关文章

【MySQL基础篇】函数及约束

1、函数 函数是指一段可以直接被另一段程序程序调用的程序或代码。 函数 - 字符串函数 MySQL中内置了很多字符串函数,常用的几个如下: 函数功能CONCAT(S1,S2,...,Sn)字符串拼接,将S1,S2,...,Sn拼接成一个字符串LOWER(str)将字符串str全部…

一文入门“机器学习-参数调整”实操

作者前言: 通过向身边的同事大佬请教之后,大佬指点我把本文的宗旨从“参数调优”改成了“参数调整”。实在惭愧,暂时还没到能“调优”的水平,本文只能通过实操演示“哪些操作会对数据训练产生影响”,后续加深学习之后,…

Python 学习中,什么是列表,如何操作列表?

什么是列表 在Python中,列表(List)是一种内置的数据结构,用于存储一系列有序的元素。列表中的元素可以是任意类型,比如整数、字符串、浮点数,甚至是另一个列表。列表是可变的(mutable&#xff…

Android系统常见的crash分类error有那些?

Android系统常见的crash分类及其对应的error主要包括以下几类: 一、Java Application Crash Java Application Crash通常是由于Java层线程因未捕获异常而终止,由系统的void uncaughtException(Thread t, Throwable e)方法进行捕获和处理。这类crash常见…

【热部署】✈️Springboot 项目的热部署实现方式

目录 🍸前言 🍻一、热部署和手动重启 🍺二、热部署的实现 2.1 手动启动热部署 2.2 自动检测热部署 2.3 关闭热部署 💞️三、章末 🍸前言 小伙伴们大家好,书接上文,通过Springboot 中的 actu…

git clone报错RPC failed; curl 92 HTTP/2 stream 7 was not closed cleanly

问题描述 git clone github上的项目报错: RPC failed; curl 92 HTTP/2 stream 7 was not closed cleanly: CANCEL (err 8) 4796 bytes of body are still expected fetch-pack: unexpected disconnect while reading sideband packet early EOF fetch-pack: invalid index-pac…

Selenium:原理与使用指南

文章目录 简介Selenium 的原理安装 Selenium基本使用示例代码说明 常用操作查找元素交互操作等待处理弹窗 高级功能截屏执行 JavaScript切换窗口 结论 简介 Selenium 是一个用于 Web 应用程序自动化测试的强大工具。它提供了一系列库和工具,支持多种浏览器和编程语…

提升TK直播体验:使用美国直播网络的六大优势

国内有许多公司想在TikTok上进行美国直播,但由于TikTok的政策限制,在国内直接访问存在困难。然而,通过使用Ogcloud的美国直播网络,这一问题得以解决。那么,TikTok海外直播使用美国直播网络具体有哪些优势呢&#xff1f…

【懒删除堆 优先队列】1172. 餐盘栈

本文涉及知识点 懒删除堆 优先队列 LeetCode1172. 餐盘栈 我们把无限数量 ∞ 的栈排成一行,按从左到右的次序从 0 开始编号。每个栈的的最大容量 capacity 都相同。 实现一个叫「餐盘」的类 DinnerPlates: DinnerPlates(int capacity) - 给出栈的最大…

封装方法实现表格合并

封装方法 const mergeTableRow (config:any)> {let data config.dataconst {mergeColNames, // 需要合并的列firstMergeColNames, // 受影响的列firstMerge // 以哪列为基础进行合并(基准列)} configif (!mergeColNames || mergeColNames.length 0) {return data}merge…

中位数贪心,3086. 拾起 K 个 1 需要的最少行动次数

一、题目 1、题目描述 给你一个下标从 0 开始的二进制数组 nums,其长度为 n ;另给你一个 正整数 k 以及一个 非负整数 maxChanges 。 Alice 在玩一个游戏,游戏的目标是让 Alice 使用 最少 数量的 行动 次数从 nums 中拾起 k 个 1 。游戏开始…

Java基础(基于韩顺平老师的笔记)

Java基础 Java特点环境搭建Java 基础语法数据类型流程控制 数组面向对象方法重载封装多态继承 类类变量(又叫静态变量)类方法(又叫静态方法) 接口枚举常用类String日期时间 集合类泛型注解异常处理多线程IO 流反射经典面试题&…

谷歌GMS认证之安卓Android Auto认证,车机的Android Auto认证介绍,GAS跟Android Auto区别

一、Android Auto认证前言 Android Auto 是谷歌(Google)推出的一个车载平台,它允许驾驶者将他们的Android设备(如智能手机)连接到车辆的显示屏上,以便在驾驶时更安全和方便地使用某些应用程序和服务。 为…

stm32中IIC通讯协议

参考资料:大部分均引用b站江协科技课程、GPT及网络资料 什么是IIC(i2C)通讯协议? 关键字:SCL、SDA、半双工、同步、串行。 IIC(Inter-Integrated Circuit),也称为I2C(In…

不同的llm推理框架

vLLM适用于大批量Prompt输入,并对推理速度要求比较高的场景。 实际应用场景中,TensorRT-LLM通常与Triton Inference Server结合起来使用,NVIDIA官方能够提供更适合NVIDIA GPU运行的高效Kernel。 LightLLM比较轻量、易于扩展、易于上手&…

【chatgpt】 PyTorch中dtype属性,表示张量的数据类型

在 PyTorch 中,dtype 是一个属性,用于表示张量的数据类型。dtype(数据类型)决定了张量中元素的存储方式和计算方法。 常见的数据类型 PyTorch 支持多种数据类型,常见的数据类型包括: torch.float32 或 t…

Linux—KVM虚拟化中使用基本命令管理虚拟机(纯实例)

🏡作者主页:点击! 👨‍💻Linux高级管理专栏:点击! ⏰️创作时间:2024年7月2日11点11分 🀄️文章质量:94分 文章目录 前言 1.查看命令帮助 2.查看KVM 的…

c/c++语言的一种日志的编写办法

今日分享一下,从某源码中看到这种日志编写方式,很强。可以借鉴。 这个函数调用的日志函数是不一样的,仔细观看: 这几种日志输出函数,背后都调用了相同的调用。 与之对应的区别就是,函数名称的差异取决于…

mpeg格式怎么转换成mp4?这四种转换方法非常好用!

mpeg格式怎么转换成mp4?在数字视频领域中,MPEG格式算是相对冷门的一种选择,然而,选择这种格式却不是没有代价的,首先,MPEG采用了有损压缩技术,这意味着在视频处理过程中,会丢失一些细…

单个企业年收入达24.7亿!银发游学市场按下“加速键”,兴趣教育平台抢滩布局

干货抢先看 1. 银发游学市场渐趋火热,美国最大的银发游学机构Road Scholar最新披露的财报显示,上个财年公司收入达3.395亿美元(约合人民币24.7亿)。 2. 在国内,一批专注银发兴趣教育的品牌纷纷入局,拓展游…