题目:求[2, n)之间的素数个数
素数的定义:
素数是指大于1的自然数,除了1和它本身之外没有其他因数的数。也就是说,素数只能被1和它本身整除,不能被其他自然数整除。
解法1
最简单的实现思路是,实现素数判断函数,然后从2~n逐个判断,然后统计素数个数
public static int countPrimes(int n) {
if(2== n){
return 1;
}
int count =0;
for(int i=2;i<n;i++){
if(isPrime(i)){
count++;
}
}
return count;
}
public static Boolean isPrime(int n) {
for(int i=2;i<n;i++){
if(0 == n%i){
return Boolean.FALSE;
}
}
System.out.println("prime=" + n);
return Boolean.TRUE;
}
解法2
观察非素数的特点,如6为非素数,它除了被1和6本身整除外,6=2*3=3*2 ,所以实际上述判断时我们判断i<sqrt[n]即可,则算法改造如下:
public static int countPrimes_2(int n) {
if(2== n){
return 1;
}
int count =0;
for(int i=2;i<n;i++){
if(isPrime_2(i)){
count++;
}
}
return count;
}
public static Boolean isPrime_2(int n) {
for(int i=2;i*i<=n;i++){
if(0 == n%i){
return Boolean.FALSE;
}
}
System.out.println("prime=" + n);
return Boolean.TRUE;
}
解法3:
再观察一下素数的整数倍,都不是素数,比如2*2=4,2*3=6,2*4=8,2*5=10...都不是
则看可以改造算法如下:初始化所有元素都是素数,然后按照素数的整数倍不是素数赋值,然后再统计素数个数
public static int countPrimes_3(int n) {
Boolean[] isPrimes = new Boolean[n];
Arrays.fill(isPrimes,Boolean.TRUE);
for(int i=2;i<n;i++){
if(isPrimes[i]){
for(int j=2*i;j<n;j+=i){
isPrimes[j] = false;
}
}
}
int count =0;
for(int i=2;i<n;i++){
if(isPrimes[i]){
count++;
}
}
return count;
}
解法4
结合2,3结论,i只要到sqrt[n]即可,而6=2*3=3*2是对称的,最终优化的算法如下
public static int countPrimes_4(int n) {
Boolean[] isPrimes = new Boolean[n];
Arrays.fill(isPrimes,Boolean.TRUE);
for(int i=2;i*i<n;i++){
if(isPrimes[i]){
for(int j=i*i;j<n;j+=i){
isPrimes[j] = false;
}
}
}
int count =0;
for(int i=2;i<n;i++){
if(isPrimes[i]){
count++;
}
}
return count;
}