每日一题——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)//2

K=int(input())

nums=set(list(map(int,input().split())))
init=nums.copy()
def Callatz(num):
    if num%2==0:
        return num//2
    else:
        return (3*num+1)//2

for 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 // 2
    else:
        result = (3 * num + 1) // 2
    memo[num] = result
    return result

for 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. 测试与调试:
  • 单元测试:为关键函数编写单元测试,确保其正确性。
  • 调试技巧:使用断点、日志输出等调试技巧,快速定位和修复问题。

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


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Openwrt路由器部分ipv6公网地址无法访问的问题

路由器是Openwrt,终端访问ipv6地址经常有些能访问,有些不能访问,一开始以为是运营商问题,后面ssh到openwrt发现所有访问都正常。 查阅资料后才知道是MTU设置问题,Openwrt 默认MTU是1492,使用IPV6应减少60个…

Word文档中公式的常用操作

一、参考资料 二、常用操作 插入公式 Alt 多行公式 Shift Enter 多行公式对齐 WORD Tips: 多行公式编辑及对齐 word自带公式等号对齐(可任意符号处对齐) 多行公式按照 为基准对齐。 拖动鼠标选中整个公式点击右键,选择【对齐点(…

[激光原理与应用-97]:激光焊接焊中检测系统系列介绍 - 1 - 什么是焊接以及传统的焊接方法

目录 一、什么是焊接 1.1 概述 1.2 基本原理 二、传统的焊接技术与方法 2.1 手工电弧焊: 1、定义与原理 2、特点 3、焊条类型 4、应用领域 5、安全注意事项 2.2 气体保护焊: 1、原理与特点 2、应用领域 3、气体选择 4、注意事项 2.3 电阻…

C++ 文达校内党员管理系统-计算机毕业设计源码20855

目 录 摘要 1 绪论 1.1研究背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2 文达校内党员管理系统系统分析 2.1 可行性分析 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能性分析 2.3 系统用例分析 2.4 系统流程分析 2.4.1 数据流程 2.5.2 业务流程 2.…

CPU/内存/综合性能评估工具汇总-3:unixbench

目录 一、概括二、UnixBench 一、概括 嵌入式开发中对要设计的产品、立项的项目进行设计时,往往需要对关键芯片进行性能评估,本文主要总结基于linux系统的产品在性能评估时的工具使用总结,在aarch64(arm64平台下测试),板卡根文件…

前端学习(三)CSS介绍及选择符

##最近在忙期末考试,因此前端笔记的梳理并未及时更新。在学习语言过程中,笔记的梳理对于知识的加深very vital.因此坚持在明天学习新知识前将笔记梳理完整。 主要内容:CSS介绍及选择符 最后更新时间:2024/7/4 目录 内容&#x…

Redis 7.x 系列【15】持久化机制之 RDB

有道无术,术尚可求,有术无道,止于术。 本系列Redis 版本 7.2.5 源码地址:https://gitee.com/pearl-organization/study-redis-demo 文章目录 1. 概述2 执行原理3. 配置项3.1 save3.2 stop-writes-on-bgsave-error3.3 rdbcompress…

HMI 的 UI 风格创造奇迹

HMI 的 UI 风格创造奇迹

关于巴图自动化Profinet协议转Modbus协议网关模块怎么配置IP地址教学

Profinet协议和Modbus协议是工业领域中常用的两种通讯协议,除此以外还有较为常见的:ModbusTCP协议,Profibus协议,Profibus DP协议,EtherCAT协议,EtherNET协议,CAN,CANOPEN等它们在自…

利用运放设计简单有源滤波器(低通、高通、带通)

本文旨在帮助刚接触模电的同学快速设计一个实用可靠的有源滤波器,故我将不会说一些晦涩难懂的原理,只给出仿真电路图。 低通滤波器 图1 低通滤波器 图1所示的是一个截止频率约为1KHz的低通滤波器。 图2 200Hz的情况 图3 2KHz的情况 设计步骤为&#x…

Lesson 47 A cup of coffee

Lesson 47 A cup of coffee 词汇 like v. 喜欢,想要 用法:like 物品 / 人 喜欢……    like 动词ing 喜欢做……(习惯性)    like to 动词原形 喜欢做……(一次性) 例句:我喜欢小狗…

一、强化学习基本概念

一、强化学习基本概念 1.1 何为强化学习?1.2 强化学习的环境1.3 强化学习的目标1.4 强化学习的数据 1.1 何为强化学习? 强化学习(Reinforcement Learning, RL)是机器通过与环境交互来实现目标的一种计算方法。机器和环境的一轮交互是指:机器在…

FlinkCDC-3.1.1 DataStream Source

问题&#xff1a; Caused by: java.lang.ClassNotFoundException: org.apache.flink.table.catalog.ObjectPath 解决&#xff1a; 在poml文件中&#xff0c;导入的flink-table依赖把“ <scope>”去掉 <properties><maven.compiler.source>8</maven.compi…

安卓稳定性之crash详解

目录 前言一、Crash 的基本原理二、Crash 分析思路三、实例分析四、预防措施五、参考链接 前言 在开发和测试 Android 应用程序时&#xff0c;遇到应用程序崩溃是很常见的情况。 Android 崩溃指的是应用程序因为异常或错误而无法正常执行&#xff0c;并且导致应用强制关闭。 一…

通过一个单相逆变器仿真深度学习PR控制器

目录 前言 ​编辑 PR控制器的理论 PR控制器不同表达式及其建模 PR控制器连续积分组合及模型 PR控制器连续传递函数及模型 PR控制器离散积分及模型 PR控制器离散传递函数及模型 PR控制器差分方程及模型 系统仿真效果 总结 前言 在项目开发中常用PI控制器&#xff0c;这次在…

java实现【 生成小程序二维码:图片+二维码备注】

1.逻辑&#xff1a;进行获取小程序的token进行-获取不限制的小程序码。2.参考的地址&#xff1a;微信官方文档&#xff1a;官网-获取不限制的小程序码 需要注意的点&#xff1a;1. 如果传入page这个参数的话必须定义check_path参数&#xff0c;不然无法识别-page指定的目录2. …

2024微信小程序期末大作业-点奶茶微信小程序(后端nodejs-server)(附下载链接)_微信小程序期末大作业百度网盘下载

菜单展示 购物车展示&#xff1a; 提交订单&#xff1a; 支付详情页展示&#xff1a; 订单查看&#xff1a; 查看历史消费&#xff1a; 部分代码展示&#xff1a; <!--pages/home/home.wxml--> <block wx:for"{{listData}}" wx:key"itemlist&qu…

国标GB28181视频汇聚平台LntonCVS视频监控安防平台与国标协议对接解决方案

应急管理部门以“以信息化推动应急管理能力现代化”为总体目标&#xff0c;加快现代信息技术与应急管理业务深度融合&#xff0c;全面支持现代应急管理体系建设&#xff0c;这不仅是国家加强和改进应急管理工作的关键举措&#xff0c;也是应对日益严峻的应急管理形势和满足公众…

数据列表组件-报表

当数据在后端接口查询到&#xff0c;需要在页面展示出来&#xff0c;如果项目有很多report &#xff0c;可以把列表做一个组件 效果如下&#xff1a; js代码&#xff1a; <!DOCTYPE html> <html> <head><meta charset"utf-8" /><title&g…

PKUMOD同学又双叒获奖啦~

近期王选所数据管理研究室的同学们 凭借在各自领域的卓越表现 获得了多项荣誉和奖励 让我们共赏风采~ 期待他们在未来的科研道路上 取得更加辉煌的成就 庞悦 前沿交叉学科研究院2020级博士生 荣获2024年北京大学校长奖学金 庞悦&#xff0c;北京大学元培学院2016级本科生&…