Woodyiiiiiii / LeetCode

My private record of Leetcode solution

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

LeetCode 204. Count Primes

Woodyiiiiiii opened this issue · comments

Count the number of prime numbers less than a non-negative number, n.

Example 1:

Input: n = 10
Output: 4
Explanation: There are 4 prime numbers less than 10, they are 2, 3, 5, 7.

Example 2:

Input: n = 0
Output: 0

Example 3:

Input: n = 1
Output: 0

Constraints:

  • 0 <= n <= 5 * 106

对于 判断素数(prime number) 问题,一般使用的是素数筛法,第一种是常用的 埃拉托色尼筛法,时间复杂度是O(nlognlogn):

    for (int i = 2; i < Math.sqrt(n); ++i) {
            if (!np[i]) {
                for (int j = i * i; j < n; j += i) {
                    np[j] = true;
                }
            }
        }
        for (int i = 2; i < n; ++i) {
            if (!np[i]) {
                ++ans;
            }
        }
        return ans;
    }
}

但该方法有个问题,一些数会被重复判定,比如12 = 2 * 6 = 3 * 4,所以引出如下欧拉筛法,也叫线性筛。

第二种是O(n)的 欧拉筛法,维护一个质数表(primes),每次用素数乘以质数表的数,排除那些非素数,并且循环是需要遍历所有数,而不是到Math.sqrt(n)为止。该筛法的核心**是让每一个合数被其最小质因数筛到。

//欧拉筛,素数筛
class Solution {
    public int countPrimes(int n) {
        int ans = 0;
        boolean[] np = new boolean[n + 1];
        List<Integer> primes = new LinkedList<>();
        for (int i = 2; i < n; ++i) {
            if (!np[i]) {
                primes.add(i);
            }
            for (int p : primes) {
                if (p * i > n) {
                    break;
                }
                np[p * i] = true;
                if (i % p == 0) {
                    break;
                }
            }
        }
        for (int i = 2; i < n; ++i) {
            if (!np[i]) {
                ++ans;
            }
        }
        return ans;
    }
}

参考资料: