Leetcode No.204 计数质数

2021-05-06 15:59:11 浏览数 (1)

题目描述

统计所有小于非负整数 n 的质数的数量。

示例 1: 输入:n = 10 输出:4 解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。

示例 2: 输入:n = 0 输出:0

示例 3: 输入:n = 1 输出:0

提示:0 <= n <= 5 * 106

思路一:暴力破解(超时)

很直观的思路是我们枚举每个数判断其是不是质数。

考虑质数的定义:在大于 1 的自然数中,除了 1 和它本身以外不再有其他因数的自然数。因此对于每个数 x,我们可以从小到大枚举 [2,x-1] 中的每个数 y,判断 y 是否为 x 的因数。但这样判断一个数是否为质数的时间复杂度最差情况下会到 O(n),无法通过所有测试数据。

代码语言:javascript复制
class Solution {
public:
    int countPrimes(int n) {
        int cnt=0;
        for(int i=2;i<n;i  ){
            if(isPrime(i)){
                cnt  ;
            }
        }
        return cnt;
    }
    bool isPrime(int m){
        if(m==0||m==1){
            return true;
        }
        for(int i=2;i<m;i  ){
            if(m%i==0){
                return false;
            }
        }
        return true;
    }
};

复杂度分析

时间复杂度:O(n^2)。

空间复杂度:O(1)。

思路二:

考虑到如果 y 是 x的因数,那么 x/y也必然是 x 的因数,因此我们只要校验 y或者x/y即可。而如果我们每次选择校验两者中的较小数,则不难发现较小数一定落在 [2,sqrt(x)]的区间中,因此我们只需要枚举 [2,sqrt(x)]中的所有数即可,这样单次检查的时间复杂度从 O(n) 降低至了 O(sqr(n))

代码语言:javascript复制
class Solution {
public:
    int countPrimes(int n) {
        int cnt=0;
        for(int i=2;i<n;i  ){
            if(isPrime(i)){
                cnt  ;
            }
        }
        return cnt;
    }
    bool isPrime(int m){
        if(m==0||m==1){
            return true;
        }
        for(int i=2;i*i<=m;i  ){
            if(m%i==0){
                return false;
            }
        }
        return true;
    }
};

复杂度分析

时间复杂度:O(n*sqrt(n))。单个数检查的时间复杂度为 O(sqrt(n)),一共要检查 O(n) 个数,因此总时间复杂度为 O(n*sqrt(n))

空间复杂度:O(1)。

0 人点赞