热门标签 | 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测试数据的人忽略掉就行了。



推荐阅读
  • AI炼金术:KNN分类器的构建与应用
    本文介绍了如何使用Python及其相关库(如NumPy、scikit-learn和matplotlib)构建KNN分类器模型。通过详细的数据准备、模型训练及新样本预测的过程,展示KNN算法的实际操作步骤。 ... [详细]
  • 本文探讨了如何在Python中将具有相同值的元素分组到矩阵中,这是一个在数据分析和处理中常见的需求。 ... [详细]
  • Go从入门到精通系列视频之go编程语言密码学哈希算法(二) ... [详细]
  • 在OpenCV 3.1.0中实现SIFT与SURF特征检测
    本文介绍如何在OpenCV 3.1.0版本中通过Python 2.7环境使用SIFT和SURF算法进行图像特征点检测。由于这些高级功能在OpenCV 3.0.0及更高版本中被移至额外的contrib模块,因此需要特别处理才能正常使用。 ... [详细]
  • 在尝试加载支持推送通知的iOS应用程序的Ad Hoc构建时,遇到了‘no valid aps-environment entitlement found for application’的错误提示。本文将探讨此错误的原因及多种可能的解决方案。 ... [详细]
  • 本文详细介绍了如何在Spring框架中设置事件发布器、定义事件监听器及响应事件的具体步骤。通过实现ApplicationEventPublisherAware接口来创建事件发布器,利用ApplicationEvent类定义自定义事件,并通过ApplicationListener接口来处理这些事件。 ... [详细]
  • 使用Vue指令实现下拉菜单效果
    使用Vue指令实现下拉菜单效果模仿重庆红岩历史革命博物馆官网的导航栏内容和效果,使用Vue实现。官网地址如下:https:www.hongyan.info官网效果效果图片展示代码展 ... [详细]
  • Requests库的基本使用方法
    本文介绍了Python中Requests库的基础用法,包括如何安装、GET和POST请求的实现、如何处理Cookies和Headers,以及如何解析JSON响应。相比urllib库,Requests库提供了更为简洁高效的接口来处理HTTP请求。 ... [详细]
  • MySQL InnoDB 存储引擎索引机制详解
    本文深入探讨了MySQL InnoDB存储引擎中的索引技术,包括索引的基本概念、数据结构与算法、B+树的特性及其在数据库中的应用,以及索引优化策略。 ... [详细]
  • OBS Studio自动化实践:利用脚本批量生成录制场景
    本文探讨了如何利用OBS Studio进行高效录屏,并通过脚本实现场景的自动生成。适合对自动化办公感兴趣的读者。 ... [详细]
  • Web动态服务器Python基本实现
    Web动态服务器Python基本实现 ... [详细]
  • Markdown 编辑技巧详解
    本文介绍如何使用 Typora 编辑器高效编写 Markdown 文档,包括代码块的插入方法等实用技巧。Typora 官方网站:https://www.typora.io/ 学习资源:https://www.markdown.xyz/ ... [详细]
  • 本文探讨了在SQL Server中处理几何类型列时遇到的INTERSECT操作限制,并提供了解决方案,包括通过转换数据类型和使用额外表结构的方法。 ... [详细]
  • Jupyter Notebook多语言环境搭建指南
    本文详细介绍了如何在Linux环境下为Jupyter Notebook配置Python、Python3、R及Go四种编程语言的环境,包括必要的软件安装和配置步骤。 ... [详细]
  • 本文介绍了一种方法,通过使用Python的ctypes库来调用C++代码。具体实例为实现一个简单的加法器,并详细说明了从编写C++代码到编译及最终在Python中调用的全过程。 ... [详细]
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社区 版权所有