每日一题——Python代码实现PAT甲级1059 Prime Factors(举一反三+思想解读+逐步优化)五千字好文

news2024/11/13 12:55:44


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

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

Python-3.12.0文档解读

目录

我的写法

代码点评

时间复杂度分析

空间复杂度分析

改进建议

我要更强

时间复杂度分析

空间复杂度分析

哲学和编程思想

预计算和缓存(Caching):

分治法(Divide and Conquer):

优化和效率:

迭代和递归:

抽象和模块化:

举一反三


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


我的写法

import math  # 导入数学模块,用于数学运算

N = int(input())  # 读取用户输入的整数
tmp = N  # 保存原始的N值,用于输出

# 定义一个函数来检查一个数是否为质数
def is_prime(num):
    if num <= 1:
        return False  # 小于等于1的数不是质数
    if num <= 3:
        return True  # 2和3是质数
    if num % 2 == 0 or num % 3 == 0:
        return False  # 能被2或3整除的数不是质数
    for i in range(5, int(math.sqrt(num)) + 1, 6):
        if num % i == 0 or num % (i + 2) == 0:
            return False  # 能被5或其后的奇数整除的数不是质数
    return True  # 如果通过了所有检查,则是质数

output = {}  # 创建一个空字典,用于存储质因数分解的结果

# 如果N是1或者N是质数,直接输出结果并退出程序
if N == 1 or is_prime(N):
    print(f"{N}={N}")
    raise SystemExit(0)

# 开始质因数分解
i = 2
while i <= N:
    if N % i == 0 and is_prime(i):  # 如果i是N的因数且是质数
        N //= i  # 将N除以i
        if i not in output:
            output[i] = 1  # 如果i不在字典中,添加i并设置其值为1
        else:
            output[i] += 1  # 如果i已在字典中,增加其值
        i -= 1  # 减少i的值,因为下一个循环会自动增加1
    i += 1  # 增加i的值,尝试下一个可能的因数

# 输出质因数分解的结果
print(f"{tmp}=", end='')
i = 0
for k, v in output.items():
    if i != 0:
        print('*', end='')  # 如果不是第一个质因数,输出乘号
    print(k, end='')  # 输出质因数
    if v > 1:
        print(f"^{v}", end='')  # 如果质因数的指数大于1,输出指数
    i += 1

代码点评

这段代码实现了对用户输入的整数进行质因数分解的功能。下面是对代码的点评:

  1. 功能实现:代码成功实现了质因数分解的基本功能,能够正确处理输入并输出分解结果。
  2. 质数检测:is_prime函数使用了优化的算法来检测质数,通过只检查到平方根的范围内,并且跳过偶数,有效地减少了不必要的计算。
  3. 质因数分解:使用了一个循环来找到质因数,并在找到后更新N的值。这种方法是正确的,但在性能优化方面还有改进空间。
  4. 输出格式:输出的格式清晰,使用了字典来存储每个质因数及其指数,便于输出和理解。

时间复杂度分析

  1. 质数检测:is_prime函数的时间复杂度在最坏情况下是O(sqrt(n)),因为只需要检查到n的平方根。
  2. 质因数分解:主循环的时间复杂度取决于找到所有质因数所需的时间。在最坏情况下,每个数都需要被检查到其平方根,因此总的时间复杂度是O(n^1.5)。然而,实际上,由于每次找到一个质因数后N的值会减小,实际的时间复杂度通常会低于这个值。

空间复杂度分析

  1. 存储质因数:使用了一个字典output来存储每个质因数及其出现的次数。在最坏情况下,如果N是一个大质数,字典的大小将等于N的位数,因此空间复杂度是O(log n)。在实际情况下,由于质因数通常远小于N,空间复杂度会更低。

改进建议

  1. 优化质因数分解:可以考虑使用更高效的算法来分解质因数,例如使用埃拉托斯特尼筛法预处理质数列表,或者使用更高效的质因数分解算法。
  2. 提前退出循环:在找到所有质因数后,可以提前退出循环,减少不必要的迭代。
  3. 代码风格:可以进一步优化代码的可读性和风格,例如添加更多的注释,使用更有意义的变量名等。

总体来说,这段代码是一个有效的质因数分解实现,但在性能和代码风格方面还有改进的空间。
 

我要更强

为了优化时间复杂度和空间复杂度,我们可以采取以下策略:

  1. 预处理质数列表:通过预先计算并存储一定范围内的质数,可以避免在每次调用is_prime时重复计算。
  2. 使用更高效的质因数分解算法:例如Pollard's rho算法或试除法优化。
  3. 优化循环:在找到所有质因数后提前退出循环。

下面是一个优化后的代码示例,使用了预处理质数列表的方法:

import math

# 预处理质数列表
def generate_primes(limit):
    primes = []
    sieve = [True] * (limit + 1)
    for num in range(2, int(math.sqrt(limit)) + 1):
        if sieve[num]:
            primes.append(num)
            for multiple in range(num * num, limit + 1, num):
                sieve[multiple] = False
    for num in range(int(math.sqrt(limit)) + 1, limit + 1):
        if sieve[num]:
            primes.append(num)
    return primes

# 使用预处理的质数列表进行质因数分解
def prime_factorization(N, primes):
    output = {}
    for prime in primes:
        if prime > N:
            break
        while N % prime == 0:
            N //= prime
            output[prime] = output.get(prime, 0) + 1
    if N > 1:
        output[N] = 1
    return output

# 主函数
def main():
    N = int(input())
    primes = generate_primes(int(math.sqrt(N)) + 1)
    factors = prime_factorization(N, primes)
    print(f"{N}=", end='')
    for factor, count in factors.items():
        if count > 1:
            print(f"{factor}^{count}", end='')
        else:
            print(f"{factor}", end='')
        if factor != list(factors.keys())[-1]:
            print('*', end='')
    print()

if __name__ == "__main__":
    main()

时间复杂度分析

  1. 预处理质数列表:使用埃拉托斯特尼筛法,时间复杂度为O(n log(log n)),其中n是预处理的上限。
  2. 质因数分解:对于每个质数,我们进行一次除法操作,直到不能再被整除。在最坏情况下,这需要O(log n)的时间复杂度。

空间复杂度分析

  1. 存储质数列表:需要存储所有小于等于sqrt(N)的质数,空间复杂度为O(sqrt(N))。
  2. 存储质因数分解结果:字典output存储每个质因数及其指数,空间复杂度为O(log N)。

通过这些优化,减少了不必要的计算,并提高了代码的效率。


哲学和编程思想

这些优化方法体现了以下哲学和编程思想:

  1. 预计算和缓存(Caching):

    • 哲学思想:这是一种“前瞻性”的思维方式,即在问题出现之前就预先准备好解决方案。在哲学上,这类似于“预防胜于治疗”的原则。
    • 编程思想:在编程中,预计算和缓存是一种常见的技术,用于存储昂贵的计算结果,以便在需要时快速检索,而不是重新计算。这可以显著提高程序的效率。
  2. 分治法(Divide and Conquer):

    • 哲学思想:分治法是一种将复杂问题分解为更小、更易于管理的部分,然后分别解决这些部分的策略。这种思想在许多哲学体系中都有体现,如“整体大于部分之和”。
    • 编程思想:在编程中,分治法是一种重要的算法设计策略,用于解决递归问题,如排序算法(快速排序、归并排序)和搜索算法(二分搜索)。
  3. 优化和效率:

    • 哲学思想:追求效率和优化是人类行为的一个基本原则,反映了“时间就是金钱”和“资源有限,需求无限”的观念。
    • 编程思想:在编程中,优化意味着寻找更有效的方法来解决问题,减少资源消耗(如CPU时间、内存使用)。这通常涉及到算法分析和选择最佳的数据结构。
  4. 迭代和递归:

    • 哲学思想:迭代和递归反映了“循环”和“重复”的概念,这在许多哲学体系中都有体现,如佛教的“轮回”和西方哲学的“永恒回归”。
    • 编程思想:迭代是通过循环结构重复执行一组指令,而递归是通过函数调用自身来解决问题。这两种方法都是编程中解决重复性问题的基本技术。
  5. 抽象和模块化:

  • 哲学思想:抽象是一种忽略细节、关注本质特征的思维方式,而模块化则是将复杂系统分解为独立、可管理的模块。这些思想在哲学中与“简化复杂性”和“关注本质”有关。
  • 编程思想:在编程中,抽象和模块化是设计清晰、可维护代码的关键。通过定义抽象数据类型和模块化代码,可以提高代码的可读性和可重用性。

通过这些哲学和编程思想的应用,可以设计出更高效、更易于理解和维护的代码。


举一反三

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

  1. 预计算和缓存技巧:
    • 在处理重复性查询或计算时,考虑使用缓存来存储结果。例如,如果你正在编写一个Web应用程序,并且某些数据查询非常耗时,可以考虑将查询结果缓存起来,以便后续请求可以快速检索。
    • 对于经常使用的函数或方法,如果它们的输出不随输入变化,可以考虑将结果存储在查找表中,以便快速访问。
  2. 分治法应用:
    • 当面对复杂问题时,尝试将其分解为更小的子问题。例如,在处理大数据集时,可以将数据集分割成小块,然后并行处理这些小块。
    • 在设计算法时,考虑是否可以通过递归或迭代的方式来解决问题。例如,排序算法(如快速排序)和搜索算法(如二分搜索)都是分治法的典型应用。
  3. 优化和效率提升:
    • 在编写代码之前,先考虑问题的最佳解决方案。了解不同算法的时间和空间复杂度,选择最适合当前问题的算法。
    • 使用性能分析工具来识别代码中的瓶颈,并专注于优化这些部分。
  4. 迭代和递归思维:
    • 对于循环问题,考虑是否可以使用迭代或递归来解决。例如,树或图的遍历通常可以使用递归实现。
    • 在设计循环时,确保有一个明确的终止条件,以避免无限循环。
  5. 抽象和模块化设计:
    • 在设计代码时,尽量使其模块化,每个模块负责一个特定的功能。这样可以提高代码的可读性和可维护性。
    • 使用抽象数据类型(如类和接口)来隐藏实现细节,只暴露必要的接口。
  6. 学习和应用设计模式:
    • 设计模式是解决常见问题的可重用解决方案。学习和应用设计模式可以帮助你更快地解决问题,并提高代码的质量。
    • 例如,单例模式可以确保一个类只有一个实例,工厂模式可以用于创建对象而不暴露创建逻辑。
  7. 持续学习和实践:
  • 编程和问题解决是一个不断学习和实践的过程。通过阅读书籍、参加在线课程、参与开源项目等方式,不断提升自己的技能。
  • 实践是提高编程能力的关键。尝试解决不同类型的问题,并将学到的知识应用到实际项目中。

通过将这些哲学和编程思想融入到你的日常工作中,你将能够更有效地解决问题,并编写出更高质量的代码。记住,编程不仅仅是写代码,更是一种思维方式和解决问题的艺术。


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

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

相关文章

渗透测试基础(六) MS10-046漏洞攻击

1. 漏洞介绍 1.1 漏洞介绍 Microsoft Windows快捷方式LNK文件自动执行代码漏洞。Windows支持使用快捷方式或LNK文件。LNK文件是指向本地文件的引用,点击LNK文件与点击快捷方式所制定的目标具有相同效果。Windows没有正确的处理LNK文件,特制的LNK文件可能导致Windows自动执行…

【Day02】0基础微信小程序入门-学习笔记

文章目录 模板与配置学习目标WXML 模板语法1.数据绑定&#xff08;类似于 Vue2 &#xff09;2. 事件绑定3. 条件渲染4.列表渲染 WXSS模板样式1. rpx尺寸单位2.样式导入3. 全局样式和局部样式 全局配置1. window2. tabBar 页面配置网络数据请求总结 持续更新~ 模板与配置 学习目…

数据挖掘常见算法(聚类)

划分方法 K-均值算法(K-means算法) 方法: 首先选择K个随机的点,称为聚类中心.对于数据集中的,每一个数据,按照距离K个中心点的距离,将其与距离最近的中心点关联起来,与同一个中心点关联的所有点聚成一类.计算每一个组的平均值,将改组所关联的中心点移动到平均值的位置重复2~…

6. Revit API UI: PreviewControl(预览控件)

6. Revit API UI: PreviewControl&#xff08;预览&#xff09; PreviewControl 有时我们需要一个预览功能&#xff0c;而Revit也提供了一个PreviewControl类来帮助我们实现这个功能。 从类的继承关系来看&#xff0c;PreviewControl就是一个用户自定义控件&#xff0c;它就…

板凳--------第20章-信号:基本概念1

tlpi_hdr.h头文件使用及设置 liao__ran 于 2020-09-29 15:12:01 发布 阅读量1.6k 收藏 5 点赞数 1 分类专栏&#xff1a; linux系统编程手册 版权 linux系统编程手册 专栏收录该内容 7 篇文章 1 订阅 订阅专栏 使用的头文件&#xff0c;主要如下&#xff1a; ename.c.inc erro…

【文字+视频教程】在手机上用文生软件平台CodeFlying开发一个整蛊版《Flappy Bird》

前言&#xff1a; 在之前的文章中我们介绍了国内首家文生软件平台码上飞CodeFlying&#xff0c;并且教给了大家如何用它来开发复杂的项目信息管理系统以及恶搞拼图小游戏等。今天就继续给大家带来一起用码上飞开发整蛊版《Flappy Bird》小游戏的教程。 老规矩&#xff0c;咱还…

024.两两交换链表中的节点,用递归和 while 循环

题意 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 难度 中等 示例 输入&#xff1a;head [1,2,3,4] 输出&#xff1a;[…

嵌入式系统中C/C++有仓颉语言对比分析

大家好,今天给大家分享一下,如何使用仓颉,以及优势在哪里? 在 2024 年 6 月 21 日的华为开发者大会上,华为不仅官宣了下一代鸿蒙操作系统 HarmonyOS NEXT,而且还正式推出了自研的编程语言 仓颉 ,可谓是赚足了面子,遥遥领先! 值得一提的是,HarmonyOS NEXT 是华为从内到…

数据库管理系统(DBMS)

一.数据库管理系统 1.简介 数据库管理系统(Database Management System)是一种操纵和管理数据库的大型软件&#xff0c;用于建立、使用和维护数据库&#xff0c;简称DBMS。它对数据库进行统一的管理和控制&#xff0c;以保证数据库的安全性和完整性。用户通过DBMS访问数据库中…

无线麦克风哪个品牌音质最好,一文告诉你无线领夹麦克风怎么挑选

随着直播带货和个人视频日志&#xff08;Vlog&#xff09;文化的兴起&#xff0c;以及自媒体内容创作的蓬勃发展&#xff0c;我们见证了麦克风行业的迅猛发展。在这一浪潮中&#xff0c;无线领夹麦克风以其无与伦比的便携性和操作效率&#xff0c;迅速赢得了广大视频制作者的喜…

WPF——属性

一、属性 类最初只有字段与函数&#xff0c;字段为一个变量&#xff0c;访问权限可以是private&#xff0c;protected&#xff0c;public。而将字段设为private&#xff0c;不方便外界对类数据的操作&#xff0c;但是将字段设为public又怕外界对数据进行非法操作&#xff0c;于…

【ChatBI】超轻量Python库Vanna快速上手,对接oneapi

oneapi 准备 首先确保你有oneapi &#xff0c;然后申请 kimi的api 需要去Moonshot AI - 开放平台 然后添加一个api key 然后打开oneapi的渠道界面&#xff0c;添加kimi。 然后点击 测试&#xff0c; 如果能生成响应时间&#xff0c;就是配置正确。 然后创建令牌 http:…

探秘美食新宠:嘴尚绝卤味,口感惊艳你的味蕾!

在繁华的都市中&#xff0c;一道独特的卤味小吃悄然走红&#xff0c;它就是“嘴尚绝卤味”。今天&#xff0c;就让我们一起走进这家卤味店&#xff0c;探寻那令人回味无穷的口感秘密。 一、初识嘴尚绝卤味 “嘴尚绝”这个名字&#xff0c;一听就让人联想到美食的极致诱惑。店内…

从零开始构建CNN模型

猫狗分类问题——从零开始构建CNN 我们将使用相同的体系结构&#xff0c;并进行一些小的更改&#xff0c;如下所示。 第一个线性层的输入尺寸发生变化&#xff0c;因为猫和狗的图像尺寸是(256,256)。添加了另一个线性层来为模型学习提供更多的灵活性。 让我们来看看实现网络架…

卷积的通俗解释

以时间和空间两个维度分别理解卷积&#xff0c;先用文字来描述&#xff1a; 时间上&#xff0c;任何当前信号状态都是迄至当前所有信号状态的叠加&#xff1b;时间上&#xff0c;任何当前记忆状态都是迄至当前所有记忆状态的叠加&#xff1b;空间上&#xff0c;任何位置状态都…

如何将视频里的语音转成文字?5种方法轻松解决

这个信息爆炸的时代&#xff0c;视频内容如同潮水般涌来&#xff0c;而我们经常需要从这些海量的视频资源中提取关键信息。无论是为了学习、工作还是娱乐&#xff0c;将视频里的语音转换成文字都是一种高效的方法。这不仅可以帮助我们更好地理解内容&#xff0c;还能方便我们进…

【自然语言处理系列】Python 字符串操作技巧:清理、替换与合并

在编写Python程序时&#xff0c;字符串处理是一项常见的任务。了解如何有效地清理、修改和合并字符串对于数据预处理、文本分析和日常编程都至关重要。本文将引导您通过一系列实用的示例来掌握Python中字符串的核心操作&#xff0c;包括去除不需要的空格和特殊字符、替换文本中…

轻松搞定数据可视化配色,这份指南助你一臂之力!

配色是数据可视化图表的主要因素。一组合适的配色可以表达数据的重点和趋势&#xff0c;而不良的配色会削弱可视化表达的有效性。在本文中&#xff0c;我将梳理数据可视化中使用的配色板类型&#xff0c;通过案例揭示数据可视化配色技巧&#xff0c;并介绍可生成配色板的插件&a…

手撕RPC——前言

手撕RPC——前言 一、RPC是什么&#xff1f;二、为什么会出现RPC三、RPC的原理3.1 RPC是如何做到透明化远程服务调用&#xff1f;3.2 如何实现传输消息的编解码&#xff1f; 一、RPC是什么&#xff1f; RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff…

Python笔记 文件的读取操作

1.open()打开函数 再Python&#xff0c;使用open函数&#xff0c;可以打开一个已经存在的文件&#xff0c;或者创建一个新文件&#xff0c;语法如下 open(name,mode,encoding) name:是要打开的文件名的字符串&#xff08;可以包含文件所在的具体路径&#xff09; mode&…