leetcode 204. Count Primes-素数统计

原题链接:204. Count Primes

按照题目“Show Hint”提示,如果定义一个函数,判断这个数是否是素数,那么效率会很低:

    public int countPrimes(int n) {
        if (n <= 2) return 0;
        int count = 1;
        boolean flag = false;
        for (int i = 3; i < n; i += 2)
            if (isPrime(i)) count++;
        return count;
    }
    public boolean isPrime(int x) {
            int tmp = (int) Math.sqrt(x);
            for (int j = 3; j <= tmp; j += 2)
                if (x % j == 0) return false;
            return true;
    }
20 / 20  test cases passed. Runtime: 460 ms  Your runtime beats 0.37% of javasubmissions.

【思路】

利用空间换时间,由于所有的合数都可以分解为素数的乘积,定义一个大小为 n 的数组,我们可以利用这个数组记录素数和合数。当我们找到一个素数时,就以这个素数为因子,找出所有以该素数为因子的合数(该合数小于 n):

    public int countPrimes(int n) {
        if (n <= 2) return 0;
        boolean[] notPrime = new boolean[n];
        int count = 1;
        for (int i = 3; i < n; i += 2) {
            if (notPrime[i]) continue;
            for (int j = 3; j * i < n; j += 2)  //找出所有以i为因子的合数,另一个因子为 j,由于素数不可能为偶数,那么 i 和 j均取做奇数
                notPrime[j * i] = true;         //将 notPrime[j * i]设置为 true,表示它是一个合数
            count++;
        }
        return count;
    }
20 / 20  test cases passed. Runtime: 15 ms  Your runtime beats 96.39% of javasubmissions.
【优化】

由于合数可以拆分为素数的乘积。那么,当我们找到一个素数时,就以这个素数为因子,找出所有以该素数为因子的合数(该合数小于 n),相对于上面的思路优化之处在于另一个因子也是素数:

public int countPrimes(int n) {
    if (n < 3) return 0;
    int primeNum = n / 2; // Count all the odd number
    boolean[] isPrime = new boolean[n];
    int sqrtN = (int) Math.sqrt(n);
    for (int i = 3; i <= sqrtN; i += 2) {
        if (!isPrime[i]) {
            for (int j = i * i; j < n; j += i * 2) {
                primeNum -= (isPrime[j])? 0: 1;
                isPrime[j] = true;
            }
        }
    }
    return primeNum;  
}
20 / 20  test cases passed. Runtime: 9 ms  Your runtime beats 100.00% of javasubmissions.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值