1

Problem

Count the number of prime numbers less than a non-negative number, n.

Note

用数组flag标记非质数,每当出现一个flag[i]为false,计数器count加一。
关于质数有三点:

  1. 大于3的质数一定是奇数,如3,5,7;
  2. 奇数中的非质数也一定是奇数的乘积。
  3. 对于一个很大的数n,它的两个因数i和j中一定有一个小于n的开方,所以我们让i <= Math.sqrt(n),j >= n,这样可以避免重复讨论一些情况。

首先,我们用i从3到Math.sqrt(n)进行标记。
其次,根据上述的第2、3两点,通过乘积i*j对应index的方法对在flag中对合数为index的值赋值true,j+=2,外层一样,i+=2,因为大于3的数中只有奇数有可能是质数,而这些质数i可以通过j的循环标记所有i作为因数的合数。
标记完所有的合数之后,再用Math.sqrt(n)到n之间的遍历,count所有未被标记true的质数。

Solution

public class Solution {
    public int countPrimes(int n) {
        boolean[] mark = new boolean[n];
        if (n <= 2) return 0;
        int i = 3, count = 1; //i from 3, so there is one prime: 2
        while (i <= Math.sqrt(n)) {
            if (!mark[i]) {
                count++;
                int j = i;
                while (i*j < n) {
                    mark[i*j] = true;
                    j += 2;
                }
            }
            i += 2;
        }
        while (i < n) {
            if (!mark[i]) count++;
            i += 2;
        } 
        return count;
    }
}

常规解法

class Solution {
    public int countPrimes(int n) {
        if (n <= 2) return 0;
        boolean[] primes = new boolean[n];
        Arrays.fill(primes, true);
        for (int i = 2; i < n; i++) {
            for (int j = i+i; j < n; j += i) {
                primes[j] = false;
            }
        }
        int count = 0;
        for (int i = 2; i < n; i++) {
            if (primes[i]) count++;
        }
        return count;
    }
}

linspiration
161 声望53 粉丝