[LeetCode] #204 计数质数

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

输入:n = 10

输出:4

解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。

暴力解法,每个数都判断是否有因数(超时)

class Solution {
    public int countPrimes(int n) {
        int ans = 0;
        for (int i = 2; i < n; ++i) {
            ans += isPrime(i) ? 1 : 0;
        }
        return ans;
    }

    public boolean isPrime(int x) {
        for (int i = 2; i < x; ++i) {
            if (x % i == 0) {
                return false;
            }
        }
        return true;
    }
}

暴力法优化

考虑到如果 y 是 x 的因数,那么 x/y​ 也必然是 x 的因数,因此我们只要校验 y 或者 x/y​​ 即可。而如果我们每次选择校验两者中的较小数,则不难发现较小数一定落在[2, 2^(1/2)]的区间中,因此我们只需要枚举 [2, 2^(1/2)] 中的所有数

class Solution {
    public int countPrimes(int n) {
        int ans = 0;
        for (int i = 2; i < n; ++i) {
            ans += isPrime(i) ? 1 : 0;
        }
        return ans;
    }

    public boolean isPrime(int x) {
        for (int i = 2; i * i <= x; ++i) {
            if (x % i == 0) {
                return false;
            }
        }
        return true;
    }
}

埃氏筛法

如果 x 是质数,那么大于 xx 的倍数2x,3x,4x...一定不是质数

class Solution {
    public int countPrimes(int n) {
        int[] isPrime = new int[n];
        Arrays.fill(isPrime, 1);
        int ans = 0;
        for (int i = 2; i < n; ++i) {
            if (isPrime[i] == 1) {
                ans += 1;
                if ((long) i * i < n) {
                    for (int j = i * i; j < n; j += i) {
                        isPrime[j] = 0;
                    }
                }
            }
        }
        return ans;
    }
}

知识点:

public static void fill(int[] a, form, to, int var)

a--数组

form--替换开始位置(包括)

to--替换结束位置(不包括)

var--要替换的值

(如果不传入from和to,则a数组全部值替换为var)

当出现i*i时,需要防溢出

总结:

posted @ 2021-09-09 17:37  1243741754  阅读(30)  评论(0编辑  收藏  举报