今天在leetcode上做了一道题,就是204题,题目是这样的统计所有小于非负整数 n 的质数的数量。示例:输入: 10,输出: 4。解释: 小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。在我以往的印象里,遇到求质数的个数,我总是一个双重for循环然后找出范围内的所有质数,然后再求个数,今天我学了一种新的求质数个数的方法,方法名如题。下来我来详细讲解下这个方法。
思路分析
首先我们来想一个观点。在给定范围内,我们把质数的倍数都去掉剩下的就都是质数,这句话在思考几遍过后我相信是没有问题的,打个比方。如题,我们现在假设n为10,我们都知道取质数从2开始取,所以
第一个质数为2,在2上画圈,其倍数4/6/8不是质数,划掉4/6/8,继续遍历
下一个质数为3,在3上画圈,其倍数6/9不是质数,划掉6/9,继续遍历
下一个质数为5,在5上画圈,没有倍数,继续遍历
以此类推,我们发现最后只剩下了2,3,5,7
也许你会问了,说了等于白说嘛,我都知道每一个质数了,我还用这样弄吗,其实我当时也是这么想的,但是我惊奇的发现即使我们不按照质数来遍历倍数,就按顺序遍历你会发现他们只剩下了质数,比如10以内,2和3遍历完了你会发现4.6.9都已经被划掉了
代码实现
代码思路是这样的我们首先创建一个长度为n的数组,然后遍历数组将里面的值都赋为1,这里我们说明一下,1代表质数,0代表非质数,也就是说我们让整个数组都代表质数,然后我们从2开始遍历数组,如果值为1的话我们就把该元素下标的倍数的元素值全变成0,表示划掉质数的倍数,一直遍历下去,然后剩下的元素为1的就是我们要找的质数了
package test;
class Test {
public static void main(String[] args) {
System.out.println(countPrimes(10));
}
public static int countPrimes(int n) {
int[] nums = new int[n];//创建一个长度为n的数组,遍历并将值置为1
for (int i = 0; i < nums.length; i++) {
nums[i] = 1;
}
for (int i = 2; i < n; i++) {
// 如果当前数为质数
if (nums[i] == 1) {
// 将对应数的倍数变为0
for (int j = 2; i * j < n; j++) {
nums[i * j] = 0;
}
}
}
//遍历数组,统计值为1的元素个数
int res = 0;
for (int i = 2; i < n; i++) {
if (nums[i] == 1)
res++;
}
return res;
}
}