每日一题——Python实现PAT甲级1015 Reversible Primes(举一反三+思想解读+逐步优化)


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

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

Python-3.12.0文档解读

目录

我的写法

is_prime函数分析:

decimal_to_base函数分析:

主循环分析:

我要更强

is_prime函数优化

decimal_to_base函数优化

完整代码及注释

优化解释

总结

哲学和编程思想

举一反三


题目链接

我的写法

# 定义函数is_prime用来检测一个数n是否为质数
def is_prime(n):# 如果n小于等于1,则它不是质数if n <= 1:return False# 如果n小于等于3,则它是质数if n <= 3:return True# 如果n能被2或3整除,则它不是质数if n % 2 == 0 or n % 3 == 0:return False# 初始化变量i为5i = 5# 循环,检测5及以上的数是否能整除nwhile i * i <= n:# 如果n能被i或i+2整除,则它不是质数if n % i == 0 or n % (i + 2) == 0:return False# 将i增加6后继续循环(6k±1的优化)i += 6# 如果上述条件都不满足,则n是质数return True# 定义函数decimal_to_base,将十进制数转换为给定的base进制
def decimal_to_base(decimal_num, base):# 如果base不在2到36之间,则返回错误信息if base < 2 or base > 36:return "Base must be between 2 and 36."# 定义一个字符串包含了可能在进制转换中用到的所有字符digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"# 如果decimal_num小于base,直接返回对应的字符if decimal_num < base:return digits[decimal_num]# 否则进行递归调用,计算decimal_num除以base的商,并将余数对应的字符附加在后面else:return decimal_to_base(decimal_num // base, base) + digits[decimal_num % base]# 主循环
while True:# 通过输入接收一行,然后分割字符串tmp=input().split()# 如果输入的长度小于2(即没有输入两个值),则退出循环if len(tmp)<2:break# 将输入的两个值转换为整数N,base=map(int,tmp)# 检查N是否为质数,以及N转换为指定进制后,翻转字符串并转换回十进制是否也为质数if is_prime(N) and is_prime(int(decimal_to_base(N,base)[::-1],base)):# 如果都是质数,则输出"Yes"print("Yes")else:# 否则输出"No"print("No")

这段代码包含两个主要的功能:一个是判断给定的整数是否为质数(is_prime函数),另一个是将十进制数转换为给定基数的表达形式(decimal_to_base函数)。最后,这两个功能在一个主循环中结合起来,以判断一个数及其在给定基数下的反转是否都是质数。

is_prime函数分析:

  • 正确性:
    • 此函数正确地实现了质数的判断,首先排除了不可能是质数的情况:小于等于1以及能够被2或3整除的数。其次利用了一个数学事实,即如果一个数n不是质数,那么它必定有一个因数小于或等于sqrt(n)。所以函数只检查到i*i <= n即可。
    • 6k±1规则被用来减少需要检查的可能因子,因为所有质数(除了2和3)都能表示成6k±1的形式。
  • 时间复杂度:
    • 在最坏的情况下(n是一个质数或者只能被另一个质数整除),这个算法的时间复杂度是O(sqrt(n)),因为它最多需要检查sqrt(n)个数字。
  • 空间复杂度:
  • 该函数使用了常数空间,除了输入值n和循环变量i之外,没有使用额外的存储空间。

decimal_to_base函数分析:

  • 正确性:
    • 函数正确地实现了基数转换,使用了递归方法。它也考虑了边界情况,即基数需要在2到36之间。
  • 时间复杂度:
    • 这个函数的时间复杂度是O(log_base(n)),因为每次递归调用都将数字n除以基数base。
  • 空间复杂度:
  • 由于使用了递归,空间复杂度也是O(log_base(n))。每次递归调用都会在调用栈中添加一层,直到达到基准情况。

主循环分析:

  • 主循环不断从用户那里接收输入,直到接收到的输入长度小于2。对于每一对输入,它会判断N是否为质数,以及N转换为指定进制后翻转字符串再转换回十进制是否也为质数。
  • 时间复杂度:
    • 主循环的时间复杂度依赖于输入的数N和基数base。质数检测有O(sqrt(N))的时间复杂度,而基数转换和反转字符串有O(log_base(N))的时间复杂度。
    • 质数检测会被执行两次,一次对原始数N,一次对翻转后的数。如果这两个数的大小相近,总的时间复杂度大约是O(sqrt(N) + log_base(N))。
  • 空间复杂度:
  • 主循环使用的空间主要取决于is_prime和decimal_to_base函数的空间复杂度,分别是O(1)和O(log_base(N))。因此,主循环的总空间复杂度大约是O(log_base(N))。

总的来说,该代码是高效和有效的,特别是在判断质数和基数转换方面使用了一些优化的方法。不过,递归可能在非常大的数字和/或基数非常高时导致栈溢出,所以在这种情况下可能需要迭代的方法来代替递归实现基数转换。


我要更强

针对前述代码,我们可以考虑一些优化策略,以提高算法的效率和减少内存使用。优化主要集中在两个方面:is_prime函数和decimal_to_base函数的改进。

is_prime函数优化

对于is_prime函数,我们已经使用了6k±1规则来减少必要的检查次数,这是一个很好的优化。进一步的优化可能不会显著减少时间复杂度,因为它本质上已经是O(sqrt(n)),这是检查质数的较快方法之一。

decimal_to_base函数优化

对于decimal_to_base函数,我们可以避免递归以减少空间复杂度。通过使用循环而不是递归,我们可以将空间复杂度降低到O(1)。

完整代码及注释

def is_prime(n):if n <= 1:return Falseif n <= 3:return Trueif n % 2 == 0 or n % 3 == 0:return Falsei = 5while i * i <= n:if n % i == 0 or n % (i + 2) == 0:return Falsei += 6return Truedef decimal_to_base(decimal_num, base):if base < 2 or base > 36:return "Base must be between 2 and 36."digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"result = ""while decimal_num > 0:result = digits[decimal_num % base] + resultdecimal_num //= basereturn result or "0"while True:tmp = input().split()if len(tmp) < 2:breakN, base = map(int, tmp)if is_prime(N) and is_prime(int(decimal_to_base(N, base)[::-1], base)):print("Yes")else:print("No")

优化解释

  • is_prime函数保持不变,因为其时间复杂度已经是针对其操作相对较优的了。
  • decimal_to_base函数已改为使用循环而非递归。这种方法相比递归,减少了额外的函数调用开销和调用栈空间使用,从而将空间复杂度降低到O(1)。循环简单地将数字按基数转换,并每次迭代将余数添加到结果字符串的前面,达到了逆序的效果。

总结

这些优化帮助减少了内存使用(尤其是在decimal_to_base函数中避免了递归),而is_prime函数的优化主要集中在减少不必要的迭代上。然而,值得注意的是,在某些情况下,优化可能带来的性能提升是有限的,尤其是当输入值非常大时。此外,代码的可读性和维护性也是在进行优化时需要考虑的因素之一。


哲学和编程思想

在优化上述代码的过程中,我们实际上应用了几个编程和软件设计的哲学和思想:

  1. KISS原则(Keep It Simple, Stupid): 此原则主张尽可能保持简单,避免不必要的复杂性。在优化decimal_to_base函数时,我们采用了一个简单的循环代替了递归,这使得函数实现更为直观且易于理解。
  2. DRY原则(Don't Repeat Yourself): 这个原则鼓励减少重复,无论是数据还是逻辑。虽然在这里的优化中没有直接体现,但保持函数的单一职责(如is_prime只检查质数)和避免在代码中重复相同的逻辑是这个原则的体现。
  3. 分治思想: 分治方法是一种将问题分解为更小部分来解决,然后合并结果以获得最终解决方案的方法。在原始代码中,decimal_to_base通过递归将大问题分解为小问题。优化后,虽然不再使用递归,但仍然通过循环逐步构建最终结果,可以看作是分治思想的一种变形应用。
  4. 时间和空间权衡: 在计算机科学中,经常需要在时间复杂度和空间复杂度之间做出权衡。例如,在递归和迭代之间选择,就需要权衡它们在时间和空间上的消耗。在这里,我们优化decimal_to_base函数,将空间复杂度降低到O(1),而保持时间复杂度不变,体现了对资源利用的权衡。
  5. 最小惊讶原则: 这个原则表明代码应该如何预期般行事,避免混淆使用者。优化后的代码更加直白和易于理解,符合这一原则。
  6. 可维护性和可读性: 优化代码的另一个考虑是确保代码的可维护性和可读性。在上述代码中,尽管我们进行了优化,但仍然保持了代码的清晰性和可读性,使得未来的维护更加容易。
  7. 渐进增强: 这是一种逐步改进代码的方法,首先实现一个简单的版本,然后逐渐增加优化和改进。例如,我们首先定义了is_prime和decimal_to_base的基本版本,然后在后续版本中对其进行了优化。
  8. 代码重构: 代码重构是改进现有代码结构而不改变其外部行为的过程。在优化decimal_to_base函数中,我们进行了重构,通过替换递归为迭代,来优化性能而不改变函数的功能。

这些哲学和思想都是编程实践中常常被采用的,目的是为了写出高效、易于维护和理解的代码。实现这些通常需要在代码的性能和其他因素(如可读性、可维护性)之间进行仔细的权衡。


举一反三

采用这些哲学和编程思想,以下是一些通用的编程技巧和最佳实践,你可以将它们应用于各种编程任务中:

  1. 追求简洁:
    • 在设计算法和编写代码时,始终问自己是否可以进一步简化。避免过度工程化,尽量不要增加不必要的复杂度。
  2. 避免重复:
    • 注意代码中的重复模式。使用函数、类或模块来封装重复的代码,以提高复用性。
  3. 逐步开发:
    • 避免一开始就尝试编写完整的复杂系统。从一个基本的、可以工作的版本开始,然后逐渐添加特性和改进。
  4. 注重可读性:
    • 书写清晰的代码,这不仅有助于别人理解,也有助于未来的你回顾和维护代码。使用有意义的变量名、保持一致的代码风格、添加注释和文档。
  5. 重构:
    • 定期审视和重构你的代码。随着项目的进行和需求的变化,始终保持代码整洁和组织良好。
  6. 性能和资源的权衡:
    • 根据应用场景,确定何时应优先考虑时间效率,何时应优先考虑空间效率。有时快速的代码需要消耗更多内存,有时节省内存的代码可能不那么快。
  7. 模块化和解耦:
    • 设计代码时,使各个部分之间的耦合最小化。每个模块或函数应负责一组明确的任务,这样可以单独测试和优化。
  8. 代码的可测试性:
    • 编写代码时考虑测试。如果代码难以测试,它可能也难以维护。使用单元测试来验证每个部分的功能。
  9. 持续学习:
    • 不断学习新的技术和方法。编程是一个快速发展的领域,而且不同的问题可能需要不同的解决策略。
  10. 错误的预期和处理:
  • 设计代码时要考虑到错误的可能性。使用异常处理、断言和合适的错误处理来提高代码的健壮性。

感谢阅读。

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

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

相关文章

Shell脚本学习_环境变量深入

目录 1.Shell环境变量深入&#xff1a;自定义系统环境变量 2.Shell环境变量深入&#xff1a;加载流程原理介绍 3.Shell环境变量深入&#xff1a;加载流程测试 4.Shell环境变量深入&#xff1a;识别与切换Shell环境类型 1.Shell环境变量深入&#xff1a;自定义系统环境变量 …

旧衣回收小程序开发,轻松回收旧衣物

随着环保理念的增强&#xff0c;回收市场得到了快速发展&#xff0c;吸引了不少年轻人进入到市场中创业。除了传统的废品回收外&#xff0c;旧衣回收也受到了大众的重视&#xff0c;市场规模迅速扩大&#xff0c;大众浪费的衣物也获得了归处。 目前旧衣回收的方式主要是线上与…

makefile与进度条

Linux项目自动化构建工具-make/makefile make是一个命令&#xff0c; makefile是一个文件&#xff0c;保存依赖关系和依赖方法。‘ touch Makefile/makefile mybin:mytest.c//依赖关系 目标文件&#xff1a;依赖文件列表 文件列表的文件之间以空格分隔 gcc -o mybin mytest.…

Shell脚本学习_字符串变量

目录 1.Shell字符串变量&#xff1a;格式介绍 2.Shell字符串变量&#xff1a;拼接 3.Shell字符串变量&#xff1a;字符串截取 4.Shell索引数组变量&#xff1a;定义-获取-拼接-删除 1.Shell字符串变量&#xff1a;格式介绍 1、目标&#xff1a; 能够使用字符串的三种方式 …

linux系统——ping命令

ping命令可以用来判断对远端ip的连通性&#xff0c;可以加域名也可以加公共ip地址 这里发送出56字节&#xff0c;返回64字节

ctfshow-web入门-命令执行(web41_exp与分析)

过滤不严&#xff0c;命令执行 preg_match(/[0-9]|[a-z]|\^|\|\~|\$|\[|\]|\{|\}|\&|\-/i, $c) 过滤掉了数字、字母以及一些符号&#xff0c;之前接触过的无字母 rce 是取反编码再取反&#xff0c;采用不可见字符去绕过正则&#xff0c;但是这里取反符号被过滤掉了&#x…

Kali linux学习入门

Kali linux学习入门 文章目录 Kali linux学习入门Kali Linux简介Kali Linux工具篇Kali Docker安装Docker 更换国内镜像源Kali 安装 docker compose Kali Linux文档篇Kali Linux 社区篇 Kali Linux简介 Kali Linux是专门用于渗透测试linux操作系统&#xff0c;它由BackTrack发展…

软件游戏找不到d3dx9_43.dll怎么办,三分钟教你解决此问题

在现代科技发展的时代&#xff0c;电脑已经成为我们生活中不可或缺的一部分。然而&#xff0c;在使用电脑的过程中&#xff0c;我们可能会遇到一些问题&#xff0c;其中之一就是电脑缺失d3dx943.dll文件。这个问题可能会影响到我们的正常使用&#xff0c;因此了解其原因和解决方…

接口(API)开发,测试工具-apifox

前言 为什么需要接口&#xff08;API&#xff09;? 因为不同的平台或系统可能使用不同的技术栈、编程语言或数据格式。API提供了一个标准化的方式&#xff0c;使得这些不同的系统可以相互交换数据和功能调用&#xff0c;实现互操作性 在开发日常的项目交互中&#xff0c;不…

PyCharm中 Fitten Code插件的使用说明一

一. 简介 Fitten Code插件是是一款由非十大模型驱动的 AI 编程助手&#xff0c;它可以自动生成代码&#xff0c;提升开发效率&#xff0c;帮您调试 Bug&#xff0c;节省您的时间&#xff0c;另外还可以对话聊天&#xff0c;解决您编程碰到的问题。 前一篇文章学习了 PyCharm…

小白教程--- kali(po解)WIFI密码 (图文教程)

kali学得好&#xff0c;牢饭少不了&#xff01;&#xff01;&#xff01; 原理&#xff1a; 模拟WiFi的已连接设备&#xff0c;强制让其下线重连&#xff0c;获取其握手包&#xff0c;使用密码字典&#xff08;宝丽&#xff09;婆洁。 环境&#xff08;准备工作&#xff09;&a…

深度解析:ChatGPT全面测评——功能、性能与用户体验全景剖析

从去年底至今&#xff0c;由 OpenAI 发布的大规模语言模型 ChatGPT 引发了几乎所有科技领域从业者的高度关注。据瑞银集团的报告显示&#xff0c;自 2023 年 1 月起&#xff0c;仅两个月内&#xff0c;ChatGPT 的月活用户数便超过了 1 亿。 ChatGPT 被誉为“最强 AI”&#xff…

操作系统总结

进程和线程的区别 本质区别&#xff1a; 进程是资源调度以及分配的基本单位。线程是 CPU 调度的基本单位。 所属关系&#xff1a;一个线程属于一个进程&#xff0c;一个进程可以拥有多个线程。地址空间&#xff1a; 进程有独立的虚拟地址空间。线程没有独立的虚拟地址空间&…

Day53 动态规划part12

LC309买卖股票的最佳时机含冷冻期 与LC122类似&#xff0c;都是可无限次购买股票&#xff0c;只不过引入了冷冻期的概念dp[i][0] 第i天持有股票收益&#xff1b;dp[i][1] 第i天不持有股票收益;情况一&#xff1a;第i天是冷静期&#xff0c;不能以dp[i-1][1]购买股票,所以以dp[…

性能测试 —— Jmeter对数据库压力测试

Jmeter先要和数据库建立连接&#xff0c;sql语句是在Jmeter中写的&#xff0c;但是语句的执行是在数据库里执行的&#xff0c;数据库再将执行结果返回给Jmeter。 在做jmeter数据库压力测试之前&#xff0c;要先检查是否有mysql-connector-java-5.1.39-bin.jar的这个包&#xf…

flink读取hive写入http接口

目录 0、创建hive数据 1、pom.xml 2、flink代码 3、sink 4、提交任务jar 5、flink-conf.yaml 6、数据接收 flink-1.17.2jdk1.8hive-3.1.3hadoop3.3.6passwordhttp0、创建hive数据 /cluster/hive/bin/beeline !connect jdbc:hive2://ip:10000 create database demo; d…

python 多任务之多进程

多任务 优势 多个任务同时执行可以大大提高程序执行效率&#xff0c;可以充分利用CPU资源&#xff0c;提高程序的执行效率 概念 是指在同一时间内执行多个任务 多进程 概念 进程&#xff08;process&#xff09;是资源分配的最小单位&#xff0c;他是操作系统进行资源分配…

鸿蒙北向开发 IDE DevEco Studio 3.1 傻瓜式安装闭坑指南

首先下载 安装IDE 本体程序 DevEco Studio 下载链接 当前最新版本是3.1.1,下载windows版本的 下载下来后是一个压缩包, 解压解锁包后会出现一个exe安装程序 双击运行安装程序 一路 next ( 这里涉及安装文件目录,我因为C盘够大所以全部默认了,各位根据自己情况选择自己的文件…

前端工程化:基于Vue.js 3.0的设计与实践

这里写目录标题 《前端工程化&#xff1a;基于Vue.js 3.0的设计与实践》书籍引言本书概述主要内容作者简介为什么选择这本书&#xff1f;结语 《前端工程化&#xff1a;基于Vue.js 3.0的设计与实践》书籍 够买连接—>https://item.jd.com/13952512.html 引言 在前端技术日…

菜品信息分页查询——后端SpringBoot

1.分页查询的逻辑&#xff1a; 页面发送ajax请求&#xff0c;将分页查询参数(page&#xff0c;pageSize, name)提交到服务端&#xff0c;获取分页数据&#xff1b; 页面发送请求&#xff0c;请求服务端进行图片下载&#xff0c;用于页面图片展示。 开发菜品信息分页查询功能&a…