LeetCode面试系列 第5天:No.204 - 统计质数

简介: LeetCode面试系列 第5天:No.204 - 统计质数

在上篇算法题的文章中,我们介绍了 LeetCode 中的一道数学题 - 快乐数 。今天,我们来聊聊质数(英文是Prime,也称为素数)相关的面试题。以前很多编程书上会有个经典问题,即判断一个数是否是质数,在那之后大家应该对判定质数的逻辑有了一定的认识。今天呢,我们来解决一个进阶问题,如何计算一个区间内素数(质数)的数量。


image.png


今天要给大家分析的面试题是 LeetCode 上第 204 号问题,

LeetCode - 204. 统计质数

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


题目描述

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

示例:

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



  • 贡献者: LeetCode

  • 题目难度: Easy

  • 通过率: 30.23%


相关话题



相似题目





解题思路:

  1. 遍历每个数,判断它是否为素数。

基于传统教科书中的算法 IsPrime(其流程见下图)来做,即在 IsPrime算法外套一个循环来做,由于下面流程的时间复杂度 T(n) = O(n*log n),于是整体算下来整个算法最后的时间复杂度为 O(n * n * log n),这个算法的时间复杂度是不达标的。


image.png


   2. 使用一个筛子,把每一个是合数的数干掉,记录其状态 isDelete,用isDelete=true表示不是质数,已被删掉,而fasle表示留下了,是质数。这个方法被称为筛法(Sieve Method)。


微信图片_20220209191340.gif


筛法又分为埃拉托斯特尼筛法(埃筛)欧拉筛(线性筛)两种埃筛是用一个数组标记是否为素数,然后依次筛去这个素数的倍数,其时间复杂度是O(n*log n)。而欧拉筛是在埃筛的基础上,让每一个合数都只被他的最小质因子筛去,从而减小时间。欧拉筛的复杂度几乎是O(n),由于其代码相对比较难理解,就不详细介绍了。

下面我们使用埃筛来统计质数数量,具体操作是从2开始维护一个bool数组isDelete来记录该数是否被删掉,依次删掉当前索引 i 的倍数,最后数组中未被删掉的值(其isDelete值为false)都是素数。


已AC代码 解法1:

  1. classSolution:
  2.    def countPrimes(self, n: int)-> int:
  3.        if n <2:
  4.            return0
  5.        else:
  6.            isDelete =[False]*n
  7.            max0 = int(math.sqrt(n))
  8.            count =0
  9.            for i in range(2, n):
  10.                if isDelete[i]==True:
  11.                    continue
  12.                count +=1

  13.                if i > max0:
  14.                    continue

  15.                for j in range(i*i, n, i):
  16.                    isDelete[j]=True
  17.        return count


ps: 由于这段代码使用了数学库函数 sqrt(),于是本地测试需要在开头引入 math库,其代码如下:

  1. import math
  2. classSolution:
  3.    def countPrimes(self, n: int)-> int:
  4.        if n <2:
  5.            return0
  6.        else:
  7.            isDelete =[False]*n
  8.            max0 = int(math.sqrt(n))
  9.            count =0
  10.            for i in range(2, n):
  11.                if isDelete[i]==True:
  12.                    continue
  13.                count +=1

  14.                if i > max0:
  15.                    continue

  16.                for j in range(i*i, n, i):
  17.                    isDelete[j]=True
  18.        return count

  19. sol =Solution()
  20. print(sol.countPrimes(5566))



微信图片_20220209191349.jpg


行用时 : 492ms, 在所有 Python3 提交中击败了 47.44%的用户.


已AC代码 解法2:

  1. classSolution:
  2.    def countPrimes(self, n: int)-> int:
  3.        if n <2:
  4.            return0
  5.        else:
  6.            isPrime =[1]*n  # isPrime = not deleted
  7.            isPrime[0]=0
  8.            isPrime[1]=0

  9.            for i in range(2, int(n**0.5)+1):
  10.                if isPrime[i]:
  11.                    isPrime[i*i:n:i]=[0]*((n-1-i*i)//i +1)   # slice: a[start:stop:step] # items from the beginning through stop-1
  12.        return sum(isPrime)



微信图片_20220209191415.jpg


执行用时 : 100ms, 在所有 Python3 提交中击败了 94.27%的用户.


参考资料:

Eratosthenes筛法(埃式筛法)时间复杂度分析 - Gavin_Nicholas的博客 - CSDN

https://blog.csdn.net/Gavin_Nicholas/article/details/88974079

目录
相关文章
|
3月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
1月前
|
存储 缓存 NoSQL
希音面试:亿级用户 日活 月活,如何统计?(史上最强 HyperLogLog 解读)
本文详细介绍了如何使用Redis的各种数据结构(如Set、Bitmap、HyperLogLog)来统计网站的日活(DAU)和月活(MAU)用户数。作者通过实际案例和代码示例,系统地讲解了这些数据结构的原理和应用场景,特别是HyperLogLog在处理亿级用户数据时的优势。文章还深入解析了HyperLogLog的数学原理和底层数据结构,帮助读者更好地理解和应用这一高效的数据统计工具。此外,文章还提供了多个相关面试题和参考资料,适合准备面试的技术人员阅读。
|
2月前
|
Kubernetes 架构师 算法
阿里面试:全国14亿人,统计出重名最多的前100个姓名
文章介绍了如何解决“从全国14亿人的数据中统计出重名人数最多的前100位姓名”的面试题,详细分析了多种数据结构的优缺点,最终推荐使用前缀树(Trie)+小顶堆的组合。文章还提供了具体的Java代码实现,并讨论了在内存受限情况下的解决方案,强调了TOP N问题的典型解题思路。最后,鼓励读者通过系统化学习《尼恩Java面试宝典》提升面试技巧。
阿里面试:全国14亿人,统计出重名最多的前100个姓名
|
4月前
|
开发者 索引 Python
这些年背过的面试题——LeetCode
本文是技术人面试系列LeetCode篇,一文带你详细了解,欢迎收藏!
|
4月前
|
存储 算法 Java
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
LeetCode初级算法题:反转链表+统计N以内的素数+删除排序数组中的重复项Java详解
48 0
|
6月前
|
存储 算法 数据挖掘
深入解析力扣168题:Excel表列名称(进制转换法详解及模拟面试问答)
深入解析力扣168题:Excel表列名称(进制转换法详解及模拟面试问答)
|
5月前
|
Python
155. 最小栈 力扣 python 空间换时间 o(1) 腾讯面试题
155. 最小栈 力扣 python 空间换时间 o(1) 腾讯面试题
|
5月前
|
存储 算法 索引
1124. 表现良好的最长时间段 (python) 前缀和 分类讨论 最大长度 力扣 面试题
1124. 表现良好的最长时间段 (python) 前缀和 分类讨论 最大长度 力扣 面试题
|
5月前
|
存储 算法
经典的滑动窗口的题目 力扣 2799. 统计完全子数组的数目(面试题)
经典的滑动窗口的题目 力扣 2799. 统计完全子数组的数目(面试题)
|
6月前
|
SQL 算法 大数据
深入解析力扣176题:第二高的薪水(子查询与LIMIT详解及模拟面试问答)
深入解析力扣176题:第二高的薪水(子查询与LIMIT详解及模拟面试问答)