热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

cprime算法_「LeetCode算法精讲」计算小于n的质数数量(Python)

题目内容统计所有小于非负整数n的质数的数量。示例:输入:10输出:4解释:小于10的质数一共有4个,它们是2,3,5,7。来源:力扣(LeetCode)链接ÿ

题目内容

统计所有小于非负整数 n 的质数的数量。

示例:

 输入: 10 输出: 4 解释: 小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/count-primes/

著作权归领扣网络所有。

运行效率
1ce1d0f7849e5d5553f74443c6aa7758.png

LeetCode的Python执行用时随缘,只要时间复杂度没有明显差异,执行用时一般都在同一个量级,仅作参考意义。

解法一(完全暴力算法):

【思路】

首先,依据质数的定义,我们得到如下算法:

遍历所有小于目标值(n)且大于等于2的整数(c);并将这些整数(c)除以小于它们(c)且大于等于2的整数(i)来判断它们是不是质数。

这样的方法显示十分麻烦,每个数(c)都要除以c-1个数才能判断完成,此时的时间复杂度为O(n^2)。

 def countPrimes(self, n: int) -> int:     def is_primes(c):         """        判断c是否为质数        """         for i in range(2, n):             if c % i == 0:                 return False         return True ​     ans = 0     for j in range(2, n):         if is_primes(j):             ans += 1     return ans

解法二(不那么暴力的暴力算法):

【思路】

实际上,并不需要除以所有小于等于某整数(c)的整数来判断该整数(c)是否为质数。

因为,除该整数(c)的平方根外,其他所有可以整除该整数的两个数,都是一个小于平方根,一个大于平方根。例如:4

所以,当除到该整数(c)的平方根时,就已经可以将所有可能的情况枚举出来了。

由此,我们对算法优化如下:

 def countPrimes(self, n: int) -> int:     def is_primes(c):         """        判断c是否为质数        """         for i in range(2, int(pow(c, 0.5)) + 1):             if c % i == 0:                 return False         return True ​     ans = 0     for j in range(2, n):         if is_primes(j):             ans += 1     return ans

解法三(更不暴力的暴力算法):

【思路】

在解法二的基础上,我们发现其实如果已经除了2,那么再除4、6等偶数都是没有意义的。

因此,我们将算法优化为只除以之前已经发现的质数,得到如下算法:

 def countPrimes(self, n: int) -> int:     prime_list = []     for c in range(2, n):         for i in prime_list:             if c % i == 0:                 break         else:             prime_list.append(c)     return len(prime_list)

解法四(使用数组标记合数):

【思路】

既然后面的数我们已经是通过之前除以之前发现的质数来判断是否为质数,那没有其实已经没有必要再继续使用耗时更高除法了。

我们可以建立一个数组,用以标记各个数是否为质数;当我们每发现一个质数,就遍历将所有该质数的倍数标记为合数;这种方法叫做“厄拉多塞筛法”。

由此,我们得到如下算法,虽然时间复杂度为O(n^2),但是不用再使用除法了:

 def countPrimes(self, n: int) -> int:     num_list = [True for _ in range(n)] ​     for i in range(2, n):         if num_list[i]:  # 如果i为质数(不是任何质数的倍数)             for j in range(2 * i, n, i):                 num_list[j] = False ​     ans = 0     for i in range(2, n):         if num_list[i]:             ans += 1     return ans

解法五(优化解法四):

【思路】

因为我们在标记7的倍数时,14、21、28、35、42都已经被2、3、5标记过了,即7*7以下的7的倍数都已经被标记了,所以,我们只需要从7*7向上标记7的倍数就可以了。

因此,当我们判断到n平方根(即标记完小于等于n平方根的最大质数)后,就不用再判断和标记了。

由此,我们得到了如下算法:

 def countPrimes(self, n: int) -> int:     num_list = [True for _ in range(n)] ​     for i in range(2, int(pow(n, 0.5)) + 1):         if num_list[i]:  # 如果i为质数(不是任何质数的倍数)             for j in range(i * i, n, i):                 num_list[j] = False ​     ans = 0     for i in range(2, n):         if num_list[i]:             ans += 1     return ans

解法六(优化解法五):

【思路】

因为在Python中,Python的内置语句往往会比我们自己写的算法要更快,因此我们更多地使用一些Python的内置语句来优化算法。

同时,在生成各元素相同的列表时,“列表生成式”的运行速度比“列表乘以常数”的运行速度要慢很多,不再使用列表生成式。

 def countPrimes(self, n: int) -> int:     if n <2:         return 0 ​     num_list &#61; [True]*n     num_list[0], num_list[1] &#61; False, False ​     for i in range(2, int(pow(n, 0.5)) &#43; 1):         if num_list[i]:  # 如果i为质数(不是任何质数的倍数)             num_list[i * i::i] &#61; [False] * ((n - i * i - 1) // i &#43; 1)  # 因为要包含i*i所以需要&#43;1&#xff1b;因为n不在列表里&#xff0c;所以需要-1 ​     return sum(num_list)  # True就是1&#xff0c;False就是0&#xff0c;可以直接统计

至此&#xff0c;其实我们的算法已经优化得很好了&#xff0c;把那些枚举LeetCode测试数据的人忽略掉就行了。



推荐阅读
  • 本文介绍如何使用 Python 编写程序,检查给定列表中的元素是否形成交替峰值模式。我们将探讨两种不同的方法来实现这一目标,并提供详细的代码示例。 ... [详细]
  • 深入理解C++中的KMP算法:高效字符串匹配的利器
    本文详细介绍C++中实现KMP算法的方法,探讨其在字符串匹配问题上的优势。通过对比暴力匹配(BF)算法,展示KMP算法如何利用前缀表优化匹配过程,显著提升效率。 ... [详细]
  • 本文介绍如何使用 Python 将一个字符串按照指定的行和元素分隔符进行两次拆分,最终将字符串转换为矩阵形式。通过两种不同的方法实现这一功能:一种是使用循环与 split() 方法,另一种是利用列表推导式。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 探讨一个显示数字的故障计算器,它支持两种操作:将当前数字乘以2或减去1。本文将详细介绍如何用最少的操作次数将初始值X转换为目标值Y。 ... [详细]
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • 本文详细介绍 Go+ 编程语言中的上下文处理机制,涵盖其基本概念、关键方法及应用场景。Go+ 是一门结合了 Go 的高效工程开发特性和 Python 数据科学功能的编程语言。 ... [详细]
  • 本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • python的交互模式怎么输出名文汉字[python常见问题]
    在命令行模式下敲命令python,就看到类似如下的一堆文本输出,然后就进入到Python交互模式,它的提示符是>>>,此时我们可以使用print() ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • Python自动化处理:从Word文档提取内容并生成带水印的PDF
    本文介绍如何利用Python实现从特定网站下载Word文档,去除水印并添加自定义水印,最终将文档转换为PDF格式。该方法适用于批量处理和自动化需求。 ... [详细]
  • 本文详细解析了Python中的os和sys模块,介绍了它们的功能、常用方法及其在实际编程中的应用。 ... [详细]
author-avatar
美煤MM就
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有