[LeetCode]54. Count Primes统计素数

Description:

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

Credits:
Special thanks to @mithmatt for adding this problem and creating all test cases.

解法1:扫描一遍,依次判断每个数是否是素数,会超时Time Limit Exceeded

class Solution {
public:
    int countPrimes(int n) {
        int cnt = 0;
        for(int i = 2; i <= n; ++i)
            if(isPrime(i)) ++cnt;
        return cnt;
    }
private:
    bool isPrime(int num) {
        for(int i = 2; i * i < num; ++i)
            if(num % i == 0) return false;
        return true;
    }
};

Hint:

  1. Let‘s start with a isPrime function. To determine if a number is prime, we need to check if it is not divisible by any number less than n. The runtime complexity of isPrime function would be O(n) and hence counting the total prime numbers up to n would be O(n2). Could we do better?
  2. As we know the number must not be divisible by any number > n / 2, we can immediately cut the total iterations half by dividing only up to n / 2. Could we still do better?
  3. Let‘s write down all of 12‘s factors:
    2 × 6 = 12
    3 × 4 = 12
    4 × 3 = 12
    6 × 2 = 12
    

    As you can see, calculations of 4 × 3 and 6 × 2 are not necessary. Therefore, we only need to consider factors up to √n because, if n is divisible by some number p, then n = p × q and since pq, we could derive that p ≤ √n.

    Our total runtime has now improved to O(n1.5), which is slightly better. Is there a faster approach?

    public int countPrimes(int n) {
       int count = 0;
       for (int i = 1; i < n; i++) {
          if (isPrime(i)) count++;
       }
       return count;
    }
    
    private boolean isPrime(int num) {
       if (num <= 1) return false;
       // Loop‘s ending condition is i * i <= num instead of i <= sqrt(num)
       // to avoid repeatedly calling an expensive function sqrt().
       for (int i = 2; i * i < num; i++) {
          if (num % i == 0) return false;
       }
       return true;
    }
  4. The Sieve of Eratosthenes is one of the most efficient ways to find all prime numbers up to n. But don‘t let that name scare you, I promise that the concept is surprisingly simple.


    Sieve of Eratosthenes: algorithm steps for primes below 121. "Sieve of Eratosthenes Animation" by SKopp is licensed under CC BY 2.0.

    We start off with a table of n numbers. Let‘s look at the
    first number, 2. We know all multiples of 2 must not be primes, so we
    mark them off as non-primes. Then we look at the next number, 3.
    Similarly, all multiples of 3 such as 3 × 2 = 6, 3 × 3 = 9, ... must not
    be primes, so we mark them off as well. Now we look at the next number,
    4, which was already marked off. What does this tell you? Should you
    mark off all multiples of 4 as well?

  5. 4
    is not a prime because it is divisible by 2, which means all multiples
    of 4 must also be divisible by 2 and were already marked off. So we can
    skip 4 immediately and go to the next number, 5. Now, all multiples of 5
    such as 5 × 2 = 10, 5 × 3 = 15, 5 × 4 = 20, 5 × 5 = 25, ... can be
    marked off. There is a slight optimization here, we do not need to start
    from 5 × 2 = 10. Where should we start marking off?
  6. In
    fact, we can mark off multiples of 5 starting at 5 × 5 = 25, because 5 ×
    2 = 10 was already marked off by multiple of 2, similarly 5 × 3 = 15
    was already marked off by multiple of 3. Therefore, if the current
    number is p, we can always mark off multiples of p starting at p2, then in increments of p: p2 + p, p2 + 2p, ... Now what should be the terminating loop condition?
  7. It is easy to say that the terminating loop condition is p < n, which is certainly correct but not efficient. Do you still remember Hint #3?
  8. Yes, the terminating loop condition can be p < √n, as all non-primes ≥ √n must have already been marked off. When the loop terminates, all the numbers in the table that are non-marked are prime.

    The Sieve of Eratosthenes uses an extra O(n) memory and its runtime complexity is O(n log log n). For the more mathematically inclined readers, you can read more about its algorithm complexity on Wikipedia.

    public int countPrimes(int n) {
       boolean[] isPrime = new boolean[n];
       for (int i = 2; i < n; i++) {
          isPrime[i] = true;
       }
       // Loop‘s ending condition is i * i < n instead of i < sqrt(n)
       // to avoid repeatedly calling an expensive function sqrt().
       for (int i = 2; i * i < n; i++) {
          if (!isPrime[i]) continue;
          for (int j = i * i; j < n; j += i) {
             isPrime[j] = false;
          }
       }
       int count = 0;
       for (int i = 2; i < n; i++) {
          if (isPrime[i]) count++;
       }
       return count;
    }

Subscribe to see which companies asked this question

解法2:Hint的第二种解法,埃拉托斯特尼筛法。这个算法的过程如下图所示,我们从2开始遍历到根号n,先找到第一个质数2,然后将其所有的倍数全部标记出来,然后到下一个质数3,标记其所有倍数,依次类推,直到根号n,此时数组中未被标记的数字就是质数。我们需要一个n-1长度的bool型数组来记录每个数字是否被标记,长度为n-1的原因是题目说是小于n的质数个数,并不包括n。

class Solution {
public:
    int countPrimes(int n) {
        vector<int> isPrime(n, 1);
        for(int i = 2; i * i < n; ++i)
        {
            if(isPrime[i] == 1)
            {
                for(int j = i * i; j < n; j += i)
                    isPrime[j] = 0;
            }
        }
        int cnt = 0;
        for(int i = 2; i < n; ++i)
            if(isPrime[i]) ++cnt;
        return cnt;
    }
};
时间: 2024-08-02 15:34:01

[LeetCode]54. Count Primes统计素数的相关文章

LeetCode:Count Primes - 统计质数数量

1.题目名称 Count Primes(统计质数数量) 2.题目地址 https://leetcode.com/problems/count-primes/ 3.题目内容 英文:Count the number of prime numbers less than a non-negative number, n. 中文:统计正整数n以内(不含n本身)质数的数量 4.一个TLE的方法 从1到n,考察每个数字是否为质数.这个方法由于花费时间较长,不能满足题目中对时间的要求. 一段实现此方法的Jav

(LeetCode)Count Primes --- 统计素数(质数)

Description: Count the number of prime numbers less than a non-negative number, n. Credits: Special thanks to @mithmatt for adding this problem and creating all test cases. Hint: Let's start with a isPrime function. To determine if a number is prime,

LeetCode 204. Count Primes(线性素数筛)

题目 题意:求[1-n)中的质数. 题解:判断一个数是否是素数,很简单, for(int i=2;i * i < x ;i++) { if(x%i==0) return false; } return true; 但是这样做明显会超时,所以我们用素数筛,来快速的求出1-n的所有素数.素数筛的原理,就是所有素数的倍数都是合数,求出一个素数,就把它的倍数都筛掉. 但是这样有一个问题,就是会筛两次,比如素数2会把30给筛掉,5 也会把30给筛掉.所以这个效率就是O(n)的,O(n)效率的素数筛,是欧拉

Leetcode problem-204 Count Primes 题解

Leetcode problem-204 Count Primes Count the number of prime numbers less than a non-negative number, n. 题解:这道题如果对每个小于n的数都进行判断是否为素数并计数会超时,因此采用筛法来解这题.建一个数组,从2开始, 把其倍数小于N的都删掉. class Solution { public: int countPrimes(int n) { vector<int>arr(n,1); int s

leetcode 204. Count Primes 找出素数的个数 ---------- java

Description: Count the number of prime numbers less than a non-negative number, n. 找出小于n的素数个数. 1.用最淳朴的算法果然超时了. public class Solution { public int countPrimes(int n) { if (n < 2){ return 0; } int result = 0; for (int i = 2; i < n; i++){ if (isPrimes(

leetcode 204. Count Primes(线性筛素数)

Description: Count the number of prime numbers less than a non-negative number, n. 题解:就是线性筛素数的模板题. class Solution { public: int countPrimes(int n) { int ans=0; vector<int>is_prime(n+1,1); for(int i=2;i<n;i++){ if(is_prime[i]){ ans++; for(int j=2*

LeetCode Count Primes 求素数个数

题意:给一个数n,返回小于n的素数个数. 思路: 1 class Solution { 2 public: 3 int countPrimes(int n) { 4 bool* isPrime =new bool[n] ; 5 6 memset(isPrime,1,n); 7 8 for(int i=2; i*i<n; i++) 9 { 10 if(!isPrime[i]) continue; 11 for(int j=i*i; j<n; j+=i) isPrime[j]=0; 12 } 13

LeetCode (36) Count Primes

题目描述 Count the number of prime numbers less than a non-negative number, n. 本题要求我们求出小于n的数中共有多少个质数.相信大部分同学在刚开始学习C语言的时候估计都写过判断一个数为质数的程序.一般的思路为: bool isPrime(int num) { int s = sqrt(num) + 1; for( int i = 3; i != s; ++i) { if (num mode i == 0) return fal

[LeetCode 204] Count Primes

题目链接:count-primes Description: Count the number of prime numbers less than a non-negative number, n public class Solution { public int countPrimes(int n) { if(n <= 2) return 0; List<Integer> primes = new ArrayList<Integer>(); primes.add(2);