题目要求:统计n以内的素数个数
测试:n等于100为例
暴力算法
public class Sushu {
public static void main(String[] args) {
System.out.println(bf(100));
}
//暴力算法
public static int bf(int n) {
int count = 0;
for(int i = 2;i < n;i++) {
count += isPrime(i) ? 1:0;
}
return count;
}
private static boolean isPrime(int x) {
for(int i = 2;i < x;i++) {
if(x % i == 0) {
return false;
}
}
return true;
}
}
存在的问题
暴力算法的时间复杂度是比较大的,可以进行以下的优化。
实际上,在isPrime函数中,for循环内判断条件可以直接改为i * i <= x,这是因为前半部分和后半部分是重复的。
埃氏筛选
主要思想:将所有的数放入布尔数组并做上标记,如果判断出已经是素数,那么它的倍数均不是素数,直接将其标记为true。
public class Sushu {
public static void main(String[] args) {
System.out.println(eratosthenes(100));
}
private static boolean isPrime(int x) {
for(int i = 2;i < x;i++) {
if(x % i == 0) {
return false;
}
}
return true;
}
//埃氏筛法
public static int eratosthenes(int n) {
//创建bool类型的数组作为标记位
boolean[] isPrime = new boolean[n]; //false代表素数
int count = 0;
for(int i = 2; i < n; i++) {
if(!isPrime[i]) {
count++;
//j是合数的标记位
for(int j = 2 * i;j < n;j+=i) {
isPrime[j] = true;
}
}
}
return count;
}
}
优化
public static int eratosthenes(int n) {
//创建bool类型的数组作为标记位
boolean[] isPrime = new boolean[n]; //false代表素数
int count = 0;
for(int i = 2; i < n; i++) {
if(!isPrime[i]) {
count++;
//j是合数的标记位
//优化:将j的初始条件改为i*i,因为每次都从2*i开始会造成重复的标记
for(int j = i * i;j < n;j+=i) {
isPrime[j] = true;
}
}
}
return count;
}