您的位置:首页 > 其它

Leetcode题目总结-Math-如何判断素数?

2017-08-13 11:58 453 查看
  今天做了一道很有意思的题目,leetcode上的204 Count primes.

  

  题目:Count the number of prime numbers less than a non-negative number,
n.

  刚看到这道题目的时候,在想....小学生的题目,于是按照常规的判断方法即只能被1和本身这个数整除的数是素数。按照这个思路我写出了第一个解决方案。

  My Solution1:

public int countPrimes(int n) {
if(n == 0 || n == 1) return 0;
//0和1不适素数

int count = 0;//纪录素数个数
boolean flag = true; //判断是否为素数的标志
for(int i = 2; i < n; i++ ){
//遍历n里面的所有数,来判断是否为素数
for(int j = 2; j < i; j++){
if(i%j == 0){
flag = false;
break;
}
}
if(flag) count ++;
flag = true;
}
return count;
}
}

结果gg了,显示  time limit exceeded!

于是,想了想上述判断方法,明显存在效率极低的问题。对于每个数n,其实并不需要从2判断到n-1,我们知道,一个数若可以进行因数分解,那么分解时得到的两个数一定是一个小于等于sqrt(n),一个大于等于sqrt(n),据此,上述代码中并不需要遍历到n-1,遍历到sqrt(n)即可,因为若sqrt(n)左侧找不到约数,那么右侧也一定找不到约数。

  My Solution2:

public int countPrimes(int n) {
if(n == 0 || n == 1) return 0;

int count = 0;
boolean flag = true;
for(int i = 2; i < n; i++ ){
for(int j = 2; j <= Math.sqrt(i);j++){
if(i%j == 0){
flag = false;
break;
}
}
if(flag) count ++;
flag = true;
}
return count;
}
}

  结果还是gg,time limit exceeded!

 
这就说明最开始的思路是不对的。没办法,百度了一下这道题目用到了一个算法 埃拉托色尼筛法算法。
下面介绍一下这个算法。

1)先把1删除(现今数学界1既不是质数也不是合数)

(2)读取队列中当前最小的数2,然后把2的倍数删去

(3)读取队列中当前最小的数3,然后把3的倍数删去

(4)读取队列中当前最小的数5,然后把5的倍数删去

(5)如上所述直到需求的范围内所有的数均删除或读取(即某个素数的平方等于最后一个数)

My Solution3:

public class Solution {
public int countPrimes(int n) {
if(n == 0 || n == 1) return 0;

boolean[] notprime = new boolean
;
// 默认所有的元素值都会设置成false; boolean的初始值为false
notprime[0] = true;
notprime[1] = true;
//前两个数都不是素数

for(int i = 2; i * i < n; i++){ //当某个素数的平方等于或者大于n的时候,判断结束
if(!notprime[i]){ //如果I是素数,那么
for(int j = 2; i * j < n; j++){
notprime[i*j] = true;
}
}
}

int count = 0;
for(boolean notP : notprime){
if(!notP) count++;
}

return count;

}
}

跑下来其实效率也不是很高,后面我发现有重复的地方:

for(int i = 2; i * i < n; i++){
if(!notprime[i]){
for(int j = 2; i * j < n; j++){ //这里有大量的数字重复,比如当i=2时候,j =2,3,...;当i=3是,j= 2,3,..

4000
notprime[i*j] = true; //此时2*3在i = 2时候已经判断过; i = 3没有必要再判断。
}
}
}


改正为:

for(int i = 2; i * i < n; i++){
if(!notprime[i]){
for(int j = i; i * j < n; j++){
notprime[i*j] = true;
}
}
}

 这样就好了!!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息