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

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

今天要给大家分析的面试题是 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%

相关话题

  • 哈希表

    https://leetcode-cn.com/tag/hash-table/

  • 数学

    https://leetcode-cn.com/tag/math

相似题目

  • 丑数

    https://leetcode-cn.com/problems/ugly-number/     难度: 简单

  • 丑数 II

    https://leetcode-cn.com/problems/ugly-number-ii/   难度: 中等

  • 完全平方数

    https://leetcode-cn.com/problems/perfect-squares/    难度: 中等


解题思路:

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

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

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

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

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

已AC代码 解法1:

  1. class Solution:

  2. def countPrimes(self, n: int) -> int:

  3. if n < 2:

  4. return 0

  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. class Solution:

  3. def countPrimes(self, n: int) -> int:

  4. if n < 2:

  5. return 0

  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))

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

已AC代码 解法2:

  1. class Solution:

  2. def countPrimes(self, n: int) -> int:

  3. if n < 2:

  4. return 0

  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)

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

参考资料:

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

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

系列文章

LeetCode面试系列 第4天:No.202 - 快乐数

(0)

相关推荐

  • 羊哥当时自学数据结构和算法的9大工具,昨晚七夕连夜肝出来了!

    小伙伴们,周末快乐! 大家都知道,数据结构和算法一直是学习编程和求职路上的一个大的拦路虎,而且不管是大厂还是小厂,在笔试和面试时都是在重点考察数据结构 算法题. 应大家的要求,这篇文章就把自己当时在学 ...

  • 找素数的两种方法

    方法一:根据特点直接找 质数(prime number)又称素数,有无限个.质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数. 根据这个性质,我们可以构造一个两层嵌套循环根据这个判断条件 ...

  • Leetcode面试系列 第1天:Leetcode 89 - 格雷码

    最近,打算花点时间写个 Python 解决 Leetcode 题的系列文章~ 大家是否还记得电影黑客帝国中的数字雨林的场景?事实上,计算机底层数据的存储和运算都是二进制的,因而面试题环节中面试官也经常 ...

  • LeetCode面试系列 第2天:No.136 - 只出现一次的数

    LeetCode面试题题系列的上一篇文章 Leetcode面试系列 第1天:Leetcode 89 - 格雷码 中,我们介绍了 二进制相关 的一个典型题. 今天呢,咱们来聊聊哈希表(字典),这是另一种 ...

  • LeetCode面试系列 第3天:No.67 - 二进制数求和

    大家都知道 LeetCode 中的第一道题是 Two Sum,比较简单.我们今天决定挑一个与之类似,但难度稍大于之的问题 二进制之和来分析,其中涉及到的主要知识是 Python 中的 进制转换,比如后 ...

  • LeetCode面试系列 第4天:No.202 - 快乐数

    或许你不知道的是,Leetcode 中是有很多 数学题 的,本文要解析的题 快乐数 就是其中到一个典型问题,本题将基于数据结构 set 来求解. 今天要给大家分析的面试题是 LeetCode 上第 2 ...

  • LeetCode面试系列 第6天:No.9 - 回文数

    上一篇面试题中,我们使用了 埃拉托斯特尼筛法 去统计给定范围内质数的个数(LeetCode No.204),还是有点烧脑的.今天我们来分析一道相对轻松的字符串面试题吧,恰好大家从Python 100天 ...

  • LeetCode面试系列 第7天:No.13 - 罗马数字转整数

    上一篇 LeetCode 面试题中,我们分析了一道轻松的字符串面试题 - 回文数.今天我们来分析一道将数学和字符串结合起来的的面试题. Leetcode 今天要给大家分析的面试题是 LeetCode ...

  • LeetCode面试系列 第8天:No.58 - 最后一个单词的长度

    上一篇 LeetCode 面试题中,我们分析了一道将数学和字符串结合起来的的面试题,今天我们再来分析了一道轻松的字符串面试题吧~ Leetcode 今天要给大家分析的面试题是 LeetCode 上第 ...

  • LeetCode面试系列 第9天:No.345 - 反转字符串中的元音字母

    上一篇 LeetCode 面试题中,我们分析了一道相对轻松的字符串面试题 - 最后一个单词的长度.今天,我们接着来看另一道字符串的算法题吧. Leet code 今天要给大家分析的面试题是 LeetC ...

  • LeetCode面试系列 第10天:No.976 - 三角形的最大周长

    上一篇 LeetCode 面试题中,我们分析了一道字符串的算法题 - 反转字符串中的元音字母,今天我们来分析一道简单的几何题吧. Leetcode 今天要给大家分析的面试题是 LeetCode 上第 ...