问题描述

统计小于非负数n的素数个数是一个经典的算法问题。我们需要编写一个函数,给定一个非负整数n,返回小于n的素数的个数。素数是指只能被1和自身整除的正整数。例如,输入n=10,我们要统计小于10的素数个数,得到的结果是4,因为小于10的素数有2、3、5、7。

算法思路

要解决这个问题,我们可以使用埃拉托色尼筛选法(Sieve of Eratosthenes)。该算法的基本思想是,从小到大遍历所有数,并将其倍数标记为合数(非素数),直到遍历完所有小于n的数。最后,剩下的没有被标记的数就是素数。

下面是算法的具体步骤:

  1. 创建一个长度为n的布尔数组isPrime,并将所有元素初始化为true。
  2. 将isPrime[0]和isPrime[1]标记为false,因为0和1不是素数。
  3. 从2开始遍历数组,若isPrime[i]为true,则将i的倍数isPrime[j](j=i*i,j+=i,直到j小于n)标记为false。
  4. 遍历结束后,统计isPrime数组中值为true的元素个数,即为小于n的素数个数。

代码实现

public int countPrimes(int n) {
    boolean[] isPrime = new boolean[n];
    Arrays.fill(isPrime, true);
    isPrime[0] = false;
    isPrime[1] = false;
    
    for (int i = 2; i * i < n; i++) {
        if (isPrime[i]) {
            for (int j = i * i; j < n; j += i) {
                isPrime[j] = false;
            }
        }
    }
    
    int count = 0;
    for (boolean prime : isPrime) {
        if (prime) {
            count++;
        }
    }
    
    return count;
}

以上代码是使用Java语言实现统计素数个数的函数。函数接收一个非负整数n作为参数,返回小于n的素数个数。函数首先创建一个长度为n的布尔数组isPrime,并将所有元素初始化为true。然后,按照上述算法步骤进行标记和统计。最后,返回统计结果。

算法分析

埃拉托色尼筛选法是一种高效的算法,其时间复杂度为O(nlog(logn)),其中n是给定的非负整数。算法的核心是标记合数,而不是遍历所有数判断是否为素数,因此大大提高了效率。

需要注意的是,虽然该算法在时间上具有较高的效率,但需要使用较大的内存空间来存储布尔数组isPrime。对于较大的n,可能会导致内存溢出的问题。因此,在实际应用中,需要根据具体情况进行优化,并考虑使用其他的算法或数据结构来解决该问题。