LeetCode_素数筛_中等_204.计数质数

x33g5p2x  于2022-01-17 转载在 其他  
字(1.5k)|赞(0)|评价(0)|浏览(329)

1.题目

给定整数 n ,返回所有小于非负整数 n 的质数的数量

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

示例 2:
输入:n = 0
输出:0

示例 3:

输入:n = 1
输出:0

提示:
0 <= n <= 5 * 106

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-primes

2.思路

(1)判断素数法
该思路比较容易想到,即用变量 cnt 记录质数的个数,遍历每一个小于 n 的非负整数,然后依次对其进行判断,如果是质数,则 cnt++,遍历结束后直接返回 cnt 即可。但这样的效率较低,并且在LeetCode中提交运行时会出现运行时间超时的问题!
(2)埃拉托斯特尼筛法(Sieve of Eratosthenes)
其主要思想是把小于根号 n 的所有素数的倍数剔除掉(或者做特殊标记),那么剩下(或为做标记)的数就都是素数
(3)欧拉筛法
其主要思想是在埃拉托斯特尼筛法的基础上,让每个合数只被它的最小质因子筛选一次,从而达到不重复筛选的目的

3.代码实现(Java)

  1. //思路1————判断素数法
  2. public int countPrimes(int n) {
  3. int cnt = 0;
  4. for (int i = 0; i < n; i++) {
  5. //判断 i 是否为质数/素数
  6. if (isPrime(i)) {
  7. cnt++;
  8. }
  9. }
  10. return cnt;
  11. }
  12. //判断非负整数 n 是否为素数/质数,若为素数/质数返回true,否则返回false
  13. public boolean isPrime(int n) {
  14. if (n == 0 || n == 1) {
  15. return false;
  16. }
  17. if (n == 2) {
  18. return true;
  19. }
  20. for (int i = 2; i <= Math.sqrt(n); i++) {
  21. if (n % i == 0) {
  22. return false;
  23. }
  24. }
  25. return true;
  26. }
  1. //思路2————埃拉托斯特尼筛法
  2. public int countPrimes(int n) {
  3. int cnt = 0;
  4. //primes[i] == true:表示非负整数 i 是质量/素数
  5. boolean[] primes = new boolean[n];
  6. //将primes初始化,假设全部是素数
  7. Arrays.fill(primes, true);
  8. //使用埃拉托斯特尼筛法将非素数标记为false
  9. for (int i = 2; i * i < n; i++) {
  10. if (primes[i] == true) {
  11. //将小于根号 n 的所有素数的倍数标记为 false
  12. for (int j = i * i; j < n; j += i) {
  13. primes[j] = false;
  14. }
  15. }
  16. }
  17. for (int i = 2; i < n; i++) {
  18. if (primes[i] == true) {
  19. cnt++;
  20. }
  21. }
  22. return cnt;
  23. }
  1. //思路3————欧拉筛法
  2. public static int countPrimes(int n) {
  3. int cnt = 0;
  4. int[] primes = new int[n];
  5. byte[] check = new byte[n];
  6. for (int i = 2; i < n; i++) {
  7. if (check[i] == 0) {
  8. //当前非负整数 i 是素数,将其保存到 primes 中
  9. primes[cnt++] = i;
  10. }
  11. for (int j = 0; j < cnt && i * primes[j] < n; j++) {
  12. //将数组 prime 里面纪录的素数,升序来当作要标记非素数的最小因子
  13. check[i * primes[j]] = 1;
  14. if (i % primes[j] == 0) {
  15. break;
  16. }
  17. }
  18. }
  19. return cnt;
  20. }

相关文章