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;
}
}
}
这样就好了!!!!
题目: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;
}
}
}
这样就好了!!!!
相关文章推荐
- 如何判断一个数是否为素数(zt)
- leetcode 题目总结(暂时按照此分类刷)
- Codeforces #270 A. Design Tutorial: Learn from Math(数论:素数判断)
- [leetcode] String类型题目总结
- Leetcode中的回溯法题目总结:八皇后问题; unique path问题;subsets问题
- 【经验总结】跪求指导:如何判断图片是否加载完成
- leetcode做题总结,题目Clone Graph 133
- leetcode做题总结,题目Search Insert Position 2012/03/03
- leetcode题目总结<4>
- leetcode做题总结,题目Container With Most Water------ 2012/01/08
- leetcode做题总结,题目Integer to Roman 2012/01/15
- leetcode做题总结,题目Swap Nodes in Pairs 2012/02/14
- LeetCode 题目总结/分类
- 如何判断一个数是否为素数(质数)?
- 【程序45】 题目:判断一个素数能被几个9整除
- LeetCode 题目总结/分类
- 如何判断一个数是否为素数
- LeetCode 题目总结
- LeetCode 题目总结/分类
- 2016年1月24日 第一场比赛 素数判断题目