素数を数える
1.はじめに
非負の整数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;
}
}