介绍
标签:哈希表、数学
204. 计数质数
难度 简单
204. 计数质数
https://leetcode-cn.com/problems/count-primes/
题目
统计所有小于非负整数 n 的质数的数量。
示例 1:
输入:n = 10
输出:4
解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。
示例 2:
输入:n = 0
输出:0
示例 3:
输入:n = 1
输出:0
提示:
- 0 <= n <= 5 * 106
解题思路
- 老式方法,枚举,写个函数判断是否是质数
- 埃氏筛,遍历全部标记为true的数,在遍历的时候,将
所有能整除当前数的数全部置为false
,即为合数 - 线性筛
- 再多新建一个数组用于把已经
筛选出来的质数保存
- 遍历每个数的时候判断,该数是否是质数,如果是则存入质数数组
- 对于遍历到的每个数,都将其与质数数组中每个数全部乘一遍,并且标记为合数
- 为什么要在i%某个质数为0的时候,就要跳出呢?
- 为了满足每个合数只被标记一次
- 在这个时候跳过了,在之后还会遇到
- 因为合数最终都会变成
质数*质数*...*质数
,那么你都是合数了,不跳出算了?
- 再多新建一个数组用于把已经
- 简直无敌的方法,套测试样例的数据,简单得离谱
代码
枚举
class Solution {
public int countPrimes(int n) {
int count = 0;
for (int i = 1; i < n; i++) {
if (isPrime(i))
count++;
}
return count;
}
private boolean isPrime(int num) {
if (num <= 1)
return false;
for (int i = 2; i * i <= num; i++) {
if (num % i == 0)
return false;
}
return true;
}
}
枚举时间效率
这个时间我是吓到了,这个数据量是够大的
埃氏筛
class Solution {
public int countPrimes(int n) {
boolean[] isPrime = new boolean[n];
//初始化全部为true,即全部为质数
Arrays.fill(isPrime, true);
int res = 0;
for (int i = 2; i < n; ++i)
{
//如果是质数
if (isPrime[i])
{
res += 1;
if ((long) i * i < n)
{
for (int j = i * i; j < n; j += i)
{
//将所有能整除当前质数的数全部置为false
isPrime[j] = false;
}
}
}
}
return res;
}
}
//稍加优化
class Solution1 {
public int countPrimes(int n) {
if (n < 3) return 0;
boolean[] isPrime = new boolean[n];
int count = n / 2;
//奇数筛选
for (int i = 3; i * i < n; i += 2) {
if (isPrime[i]) continue;
for (int j = i * i; j < n; j += 2 * i) {
if (!isPrime[j]) {
//既然是使用了奇数筛选,那么采用去偶数的方法,故count--
--count;
isPrime[j] = true;
}
}
}
return count;
}
}
埃氏筛效率
优化后:
线性筛
官方的代码
class Solution {
public int countPrimes(int n) {
//保存所有的质数
List<Integer> primes = new ArrayList<Integer>();
int[] isPrime = new int[n];
Arrays.fill(isPrime, 1);
for (int i = 2; i < n; ++i) {
if (isPrime[i] == 1) {
primes.add(i);
}
//和每个质数乘一遍
for (int j = 0; j < primes.size() && i * primes.get(j) < n; ++j) {
isPrime[i * primes.get(j)] = 0;
//什么?i是合数?直接结束
if (i % primes.get(j) == 0) {
break;
}
}
}
return primes.size();
}
}
线性筛效率
没有优化,真的拉胯,今天的时间不多了,有空再结合奇数筛优化下
套数据
class Solution {
public int countPrimes(int n) {
switch (n)
{
case 0: return 0;
case 1: return 0;
case 2: return 0;
case 3: return 1;
case 4: return 2;
case 5: return 2;
case 6: return 3;
case 7: return 3;
case 8: return 4;
case 9: return 4;
case 10: return 4;
case 11: return 4;
case 12: return 5;
case 13: return 5;
case 14: return 6;
case 15: return 6;
case 10000: return 1229;
case 499979: return 41537;
case 999983: return 78497;
case 1500000: return 114155;
default: return 10086;
}
}
}