题目描述
统计所有小于非负整数n的质数的数量
解题思路
第一次我用了暴破,用C实现的,代码如下
#include<stdio.h>
int main(void) {
int num;
scanf("%d", &num);
int sum = countPrimes(num);
printf("%d", sum);
return 0;
}
int countPrimes(int n) {
//设置一个统计合数的计数器
int count = 0;
int i, j;
//如果n小于3,根据题意那一个质数也没有,直接返回0
if (n < 3) {
return 0;
}
//那n大于3时,挨着筛选,看该数能不能被它本身之前的数整除
for (i = 2; i < n; i++) {
for (j = 2; j < i; j++) {
if (i % j == 0) {
//如果能被它本身之前的数整数,那它是合数,计数器+1
count++;
break;
}
}
}
return n - count - 2;//n个数,减去合数,减去1和n本身剩下的就是质数的个数
}
运行结果虽然没问题
但是运行的时间超了
这个暴力解法的时间复杂度和空间复杂度显然超出预期
之后请教了一下别人了解到了埃氏筛法。
埃氏筛法:
(1)先把1删除(现今数学界1既不是质数也不是合数)
(2)读取队列中当前最小的数2,然后把2的倍数删去
(3)读取队列中当前最小的数3,然后把3的倍数删去
(4)读取队列中当前最小的数5,然后把5的倍数删去
(5)读取队列中当前最小的数7,然后把7的倍数删去
(6)如上所述直到需求的范围内所有的数均删除或读取
然后我用Java实现的,代码如下
public class Tx {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();//获取用户设定的范围数
System.out.println(countNumber(num));
}
//埃氏筛法
public static int countNumber(int n) {
int count = 0;//设置一个统计质数个数的计算器
boolean[] Array = new boolean[n];
//boolean型数组存储用户设定的个数的boolean值,数组元素为false
// 0和1都不是素数,所以直接从2开始筛选
for (int i = 2; i < Array.length; i++) {
if (!Array[i]) {
//依次划去已经挑选出来的质素的所有倍数,即是筛选出所有的非素数目标
for (int j = 2 * i; j < Array.length; j += i) {
Array[j] = true;
}
}
}
//筛选结束后,数组下标是素数的数组元素为false,非素数的为true
for (int i = 2; i < Array.length; i++) {
if (!Array[i]) {
count++;//符合条件,则计算器+1
}
}
return count;
}
}
运行结果
在下水平太差,效率只有到这一步了。