埃拉托斯特尼筛法
目的
求解1到n之间素数的个数
1. 普通方法
很质朴地遍历,然后判断每个数是否是质数
时间复杂度:
O
(
n
2
)
{O(n^2)}
O(n2)
class Solution {
public static int countPrimes(int n) {
if(n<2)return 0;
int ret = 0;
for (int i = 2; i <n ; i++) {
if(isPrime(i))ret++;
}
return ret;
}
private static boolean isPrime(int n) {
for (int i = 2; i<n ; i++) {
if(n%i==0)return false;
}
return true;
}
}
2. 普通方法优化
isPrime()
方法可以优化到
O
(
s
q
r
t
(
n
)
)
{O(sqrt(n))}
O(sqrt(n))
时间复杂度:
O
(
n
×
s
q
r
t
(
n
)
)
{O(n\times sqrt(n))}
O(n×sqrt(n))
class Solution {
public static int countPrimes(int n) {
if(n<2)return 0;
int ret = 0;
for (int i = 2; i <n ; i++) {
if(isPrime(i))ret++;
}
return ret;
}
private static boolean isPrime(int n) {
for (int i = 2; i*i<=n ; i++) {
if(n%i==0)return false;
}
return true;
}
}
3. 埃拉托斯特尼筛法普通版
思路就是我们得到一个质数K后,所有K的倍数的数都不是质数
class Solution {
public static int countPrimes(int n) {
if(n<2)return 0;
boolean[] dp = new boolean[n];
Arrays.fill(dp, true);
for (int i = 2; i <n ; i++) {
if(!dp[i])continue;
int j = i*2;
while (j < n) {
dp[j]= false;
j+=i;
}
}
int count = 0;
for (boolean item : dp) {
if(item)count++;
}
// 减去0和1
return count-2;
}
}
4. 埃拉托斯特尼筛法改进版
- 在上一段代码中,
int j = i*2
这里我们可以改成int j = i*i
- 外层的循环也可以改成
for(int i = 2;i*i<n;i++)
- 省略dp数组的初始数据填充(Arrays.fill),最后取反即可
class Solution {
public static int countPrimes(int n) {
if(n<2)return 0;
boolean[] dp = new boolean[n];
for (int i = 2; i*i <n ; i++) {
if(dp[i])continue;
int j = i*i;
while (j < n) {
dp[j]= true;
j+=i;
}
}
int count = 0;
for (boolean item : dp) {
if(!item)count++;
}
return count-2;
}
}