如何求素数(prime)个数

给定一个数字n,如何获得n以内素数的个数

这个一道Leetcode上面的题,暴力解法这里就不赘述了,主要说说一种巧妙地,时间复杂度比较低的解法。

1.前置知识

在处理这个问题之前我们需要有两点认识,第一点,我们需要知道素数的定义:只能被1和其本身整除的数,1不算素数。其次,除了2之外的偶数都不是素数。
第二点是奇数的数量必然是n/2个。

2.代码实现

    public int countPrimes(int n) {
    //因为1不算素数,所以n=0,1,2时,素数数量都为0
    if (n < 3) return 0;

    //1是奇数但不是素数,2是偶数但是素数
    //又因为奇数和偶数数量上是一样的。并且数数的起点是从奇数1开始的。所以在小于n的所有数中,必然有一半的数为奇数,剩余的数为偶数(偶数数量可能又一半,也可能小于一半)。
    //又因为偶数必然不是素数,那么我们就只需分析在`n/2`个奇数中,有多少个素数
    int count = n / 2;

    //创建一个`boolean`数组,数组下标表示每一个自然数。true默认其不是素数,false默认其为素数
    boolean[] s = new boolean[n];

    //从3开始,遍历奇数
    for(int i = 3 ;i * i < n; i += 2){
        if(s[i])continue;
        
        //如果i为奇数,则i*i也为奇数,但i*i肯定不为素数(因为他能被1,i和i*i整除)
        //i*i + i也不为素数(同理),应为一个公理:奇数加奇数等于偶数,奇数加偶数等于奇数
        //偶数必然不是素数,我们考虑奇数就行了,所以这里将步长设置为2*i,这样,他们相加必然为奇数,而且此奇数能被1,i和其本身整除,必然不为素数
        for(int j = i * i;j < n;j += 2 * i){
            if(!s[j]){
                count--;
                s[j] = true;
            }
        }
    }

    return count;
    }
posted @ 2021-03-05 11:40  LinM狂想曲  阅读(661)  评论(0编辑  收藏  举报