leetcode:204. 计数质数

题目来源

  • leetcode:204. 计数质数

题目描述

leetcode:204. 计数质数_第1张图片

class Solution {
public:
    int countPrimes(int n) {

    }
};

题目解析

素数筛法

  • 先把所有整数列出来,然后把2的倍数全部剔除,然后把3的倍数全部剔除…
  • 遍历所有素数,如果没有被划去,它一定是素数,然后把它的倍数也划去

leetcode:204. 计数质数_第2张图片

class Solution {
public:
    int countPrimes(int n) {
        // 写程序时要时刻注意边界条件
        if (n < 3){
            return 0;
        }
        
        std::vector<bool> f(n, false); // < n
        int count = n / 2; // 所有偶数都不要,还剩几个数
        for (int i = 3; i * i < n; ++i) {
            if(f[i]){
                continue;
            }

            for (int j = i * i; j < n; j += 2 * i) {
                if (!f[j]) {
                    --count;
                    f[j] = true;
                }
            }
        }
        
        return count;
    }
};

埃氏筛

准备:

  • 算术基本定理:任何一个大于1的自然数 N,如果N不为质数,那么N可以唯一分解成有限个质数的乘积
  • 若一个数可以进行因数分解,则得到的两个数一定是有一个>=sqrt(x),另一个<=sqrt(x).

算法步骤

N = 26,

  • 1、列出所有序列
    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
  • 2、找到第一个素数:0,1不是素数【去掉】,2是素数、序列变成: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
  • 3、将剩下的队列中,划掉2的倍数,序列变成:2 3 5 7 9 11 13 15 17 19 21 23 25
  • 4、如果这个序列中最大数小于最后一个标出的素数的平方,那么剩下的所有的数都是素数,否则回到第二步。
  • 5、本例中,因此25大于2的平方,我们返回第二步:
  • 6、剩下的序列中第一个素数是3,将主序列中3的倍数划掉,主序列变成:2 3 5 7 11 13 17 19 23 25
  • 7、我们得到的素数有:2,3
  • 8、25仍然大于3的平方,所以我们还要返回第二步:
    序列中第一个素数是5,同样将序列中5的倍数划掉,主序列成了:2 3 5 7 11 13 17 19 23
    9、我们得到的素数有:2,3,5 。
    10、因为23小于5的平方,跳出循环.
    结论:2到25之间的素数是:2 3 5 7 11 13 17 19 23。
class Solution {
public:
    int countPrimes(int n) {
        // 写程序时要时刻注意边界条件
        if (n < 2){
            return 0;
        }

   
        std::vector<int> arr(n, 0);// 0 表示都是素数
        arr[0] = arr[1] = 1;   // 1 表示不是素数
   
        for (int i = 2; i <= std::sqrt(n - 1); i++){
            if (arr[i] == 0){  // 没有被圈出来
                // 去掉倍数
                for (int j = i * 2; j <= n - 1 ; j = j + i){  // 2 的倍数去掉, 3的倍数去掉,5的倍数去掉
                    arr[j] = 1;  // 去掉倍数
                }
            }
        }


        int ans = 0;
        for (int value : arr) {
            if (value == 0) {
                ans++;
            }
        }

        return ans;
    }

};

优化暴力

假如一个数为 9 ,那么其二分之一(4.5)后的数都可以不用进行计算,因为肯定是有余的 。事实上情况会比这更好一些:对正整数 n ,如果用 2 到 √n 之间(包含边界)的所有整数去除,均无法整除,则 n 为质数

class Solution {
public:
    int countPrimes(int n) {
        int ans = 0;

        for (int i = 2; i < n; i++){
            if (Primes(i)){
                ans++;
            }
        }

        return ans;
    }


    static bool Primes(int n){
        bool flag = true;
        int t = (int)std::sqrt(n);
        for (int i = 2; i < t + 1; i++){
            if (n % i == 0){
                flag = false;
                break;
            }
        }

        return flag;
    }
};

类似题目

题目 思路
leetcode:204. 小于n的质数的数量 Count Primes
leetcode:279. 完全平方数 Perfect Squares

你可能感兴趣的:(算法与数据结构,leetcode,算法,职场和发展)