Leetcode——计数质数

Posted Yawn,

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode——计数质数相关的知识,希望对你有一定的参考价值。

1. 题目

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

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

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

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

提示
0 <= n <= 5 * 106

2. 题解

  • 其实遍历小于n的数,然后求出质数数量即可
  • 问题在于:如何判断质数

直接判断法:

会超时:

class Solution {
    public int countPrimes(int n) {
        int res = 0, i = 0;
        while(i < n){
            if(isPrime(i))
                res++;
            i++;
        }
        return res;
    }

//直接判断是否为质数
    public boolean isPrime(int n){
        if (n <= 3) {
            return n > 1;
        }
        for(int i = 2; i < n; i++){
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }
}

优化:

  • 对于每个数n,其实并不需要从2判断到n-1,我们知道,一个数若可以进行因数分解,那么分解时得到的两个数一定是一个小于等于sqrt(n),一个大于等于sqrt(n)
  • 据此,上述代码中并不需要遍历到n-1,遍历到sqrt(n)即可,因为若sqrt(n)左侧找不到约数,那么右侧也一定找不到约数。

emmmmmm,还是超时

class Solution {
    public int countPrimes(int n) {
        int res = 0, i = 0;
        while(i < n){
            if(isPrime(i))
                res++;
            i++;
        }
        return res;
    }

    public boolean isPrime(int n) {
    	if (n <= 3) {
        	return n > 1;
	    }
    	int sqrt = (int)Math.sqrt(n);
    	for (int i = 2; i <= sqrt; i++) {
        	if(n % i == 0) {
            	return false;
        	}
    	}
    	return true;
	}
}

继续优化:

  • 我们继续分析,其实质数还有一个特点,就是它总是等于 6x-1 或者 6x+1,其中 x 是大于等于1的自然数。
  • 如何论证这个结论呢?
    • 首先 6x 肯定不是质数,因为它能被 6 整除;其次 6x+2 肯定也不是质数,因为它还能被2整除;
    • 依次类推,6x+3 肯定能被 3 整除;6x+4 肯定能被 2 整除。那么,就只有 6x+1 和 6x+5 (即等同于6x-1) 可能是质数了。所以循环的步长可以设为 6,然后每次只判断 6 两侧的数即可。
class Solution {
    public int countPrimes(int n) {
        int res = 0, i = 0;
        while(i < n){
            if(isPrime(i))
                res++;
            i++;
        }
        return res;
    }

    public static boolean isPrime(int num) {
        if (num <= 3) 
            return num > 1;
        // 不在6的倍数两侧的一定不是质数
        if (num % 6 != 1 && num % 6 != 5) {
            return false;
        }
        int sqrt = (int) Math.sqrt(num);
        for (int i = 5; i <= sqrt; i += 6) {
            if (num % i == 0 || num % (i + 2) == 0) {
                return false;
            }
        }
        return true;
    }
}

以上是关于Leetcode——计数质数的主要内容,如果未能解决你的问题,请参考以下文章

[LeetCode] 计数质数

leetcode 204. Count Primes 计数质数 (Easy)

LeetCode Algorithm 204. 计数质数

LeetCode 204 Count Primes(质数计数)(*)

204计数质数

leetcode 简单 第五十八题 计数质数