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 204. Count Primes 计数质数 (Easy)