计数质数
一、题目简介
统计所有小于非负整数 n 的质数的数量
(题目来源:力扣(LeetCode))
示例 1:
输入:n = 10
输出:4
解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。
示例 2:
输入:n = 0
输出:0
示例 3:
输入:n = 1
输出:0
提示:
0 <= n <= 5 * 106
二、解决方法
1. 暴力法
class Solution {
public int countPrimes(int n) {
int ans = 0;
//遍历小于n且大于等于2的所有数字
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;
}
}
2. 埃氏筛
维基百科的动画:
class Solution {
public int countPrimes(int n) {
//新建一个长度为n的数组(1标记是质数,0代表不是质数)
int[] primes=new int[n];
//初始化全部为质数
Arrays.fill(primes,1);
int count=0;
for (int i = 2; i < n; i++) {
if(primes[i]==1){
//如果当前是质数,计数count++
count++;
//再从i*i开始遍历到n为止(不包含n),如果是i的倍数肯定不是质数,把它对应的下标赋值为0
if((long)i*i<n){
for (int j=i*i;j<n;j+=i){
primes[j]=0;
}
}
}
}
return count;
}
}
3. 埃氏奇数筛
如上图,我们可以看到偶数占一半,提前去除就可以省下一半的时间了(偶数必不可能为质数,除了2)
class Solution {
public int countPrimes(int n) {
//新建一个长度为n的数组(1标记是质数,0代表不是质数)
int[] primes=new int[n];
//初始化全部为质数
Arrays.fill(primes,1);
//判断当前是否超过了2(超过了2就要统计2这个质数)
int count=n>2?1:0;
for (int i = 3; i < n; i+=2) {
//每次递增改成只遍历奇数
if(primes[i]==1){
count++;
if((long)i*i<n){
for (int j=i*i;j<n;j+=i){
primes[j]=0;
}
}
}
}
return count;
}
}