#LeetCode匠#计数质数

89 阅读1分钟

「这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战」。

小学数学课本中我们第一次接触素数、偶数、质数、合数等,你还记得他们的定义么?给你一个正整数,如何使用算法高效判断一个数属于哪类数呢?今天我们分别有两种方法实现判断一个数的前面有多少个质数。

题目描述

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

题目示例

题目解法

解法一:埃氏筛选法

先初始化一个标志位的数组,而后从2开始,将其平方小于n的值逐个标记合数

/**
 * 埃氏筛选法
 */
class Solution {
    public int countPrimes(int n) {
        int[] isPrime = new int[n];
        // 装填所有值为1,标志位
        Arrays.fill(isPrime, 1);
        // 统计质数个数
        int ans = 0;
        for (int i = 2; i < n; ++i) {
            // 把未改变值的逐个更新
            if (isPrime[i] == 1) {
                ans += 1;
                // 核心逻辑,i的平方及其+i一定不是
                if ((long) i * i < n) {
                    for (int j = i * i; j < n; j += i) {
                        isPrime[j] = 0;
                    }
                }
            }
        }
        return ans;
    }
}

解法二:线性列表筛

同埃氏筛选不同的是,使用线性列表标识合数群体

/**
 * 线性列表筛
 */
class Solution {
    public int countPrimes(int n) {
        // 维护一个list
        List<Integer> primes = new ArrayList<Integer>();
        int[] isPrime = new int[n];
        // 填充标识位
        Arrays.fill(isPrime, 1);
        for (int i = 2; i < n; ++i) {
            if (isPrime[i] == 1) {
                primes.add(i);
            }
            // 标记和数
            for (int j = 0; j < primes.size() && i * primes.get(j) < n; ++j) {
                isPrime[i * primes.get(j)] = 0;
                if (i % primes.get(j) == 0) {
                    break;
                }
            }
        }
        return primes.size();
    }
}

LeetCode原题链接:204. 计数质数 - 力扣(LeetCode) (leetcode-cn.com)