原题
Description:
Count the number of prime numbers less than a non-negative number, n.
题目大意
统计小于非负整数n的素数的个数。
解题思路
使用见埃拉托色尼筛法。
埃拉托色尼筛法,是一种公元前250年由古希腊数学家埃拉托色尼所提出的一种简单检定素数的算法。
给出要筛数值的范围n,找出以内的素数。先用2去筛,即把2留下,把2的倍数剔除掉;再用下一个素数,也就是3筛,把3留下,把3的倍数剔除掉;接下去用下一个素数5筛,把5留下,把5的倍数剔除掉;不断重复下去......。
举例:求25以内的所有素数
(1) 列出2以后的所有序列:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
(2) 标出序列中的第一个素数,也就是2,划去2的倍数(用红色标出)序列变成:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
(3) 如果现在这个序列中最大数小于最后一个标出的素数的平方,那么剩下的序列中所有的数都是素数,否则回到第二步。本例中,因为25大于2的平方,我们返回第二步:
(4) 剩下的序列中第一个素数是3,再将主序列中3的倍数划出(红色),主序列变成:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
(5) 我们标出的素数有:2,3,当前25仍然大于3的平方,所以我们还要返回第二步:
现在序列中第一个素数是5,同样将序列中5的倍数划出,主序列成了:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
(6) 因为25等于5的平方,跳出循环.
结论:去掉红色的数字,2到25之间的素数是:2 3 5 7 11 13 17 19 23
下图中:
2是第一个标出的素数为红色,2的倍数为浅红色
3是第二个标出的素数为绿色,3的倍数为浅绿色
5是第三个标出的素数为蓝色,5的倍数为浅蓝色
2,3,5,加上剩余的灰色数字就是所求的素数
代码实现
算法实现类
public class Solution {
public int countPrimes(int n) {
if (n <= 1) {
return 0;
}
// 默认所有的元素值都会设置为false
boolean[] notPrime = new boolean[n];
notPrime[0] = true;
notPrime[1] = true;
for (int i = 2; i * i < n; i++) {
// 如果i是一个质数,i将i的倍数设置为非质数
// 如是i是一个合数,则它必定已经设置为true了,因为是从2开始处理的
if (!notPrime[i]) {
for (int j = 2 * i; j < n; j += i) {
notPrime[j] = true;
}
}
}
// 统计质数的个数
int result = 0;
for (boolean b : notPrime) {
if (!b) {
result++;
}
}
return result;
}
}