计数质数
统计所有小于非负整数 n 的质数的数量。
示例 1:
输入:n = 10
输出:4
解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。
示例 2:
输入:n = 0
输出:0
示例 3:
输入:n = 1
输出:0
暴力遍历
class Solution {
public int countPrimes(int n) {
int count = 0;
for (int i = 2; i < n; i++) {
count += isPrime(i) ? 1 : 0;
}
return count;
}
private boolean isPrime(int num) {
int max = (int)Math.sqrt(num);
for (int i = 2; i <= max; i++) {
if (num % i == 0)
return false;
}
return true;
}
}
厄拉多塞筛法
class Solution {
public int countPrimes(int n) {
boolean[] isComposite = new boolean[n];
int count = 0;
for (int i = 2; i < n; ++i) {
if (!isComposite[i]) {
count++;
if ((long)i * i < n) {
for (int j = i * i; j < n; j += i)
isComposite[j] = true;
}
}
}
return count;
}
}
线性筛
埃氏筛其实还是存在冗余的标记操作,比如对于 4545 这个数,它会同时被 3,53,5 两个数标记为合数。线性筛只标记质数集合中的数与 x 相乘的数,即 x ⋅ primes 0 , x ⋅ primes 1 , … x\cdot\textit{primes}_0,x\cdot\textit{primes}_1,\ldots x⋅primes0,x⋅primes1,…,且在发现 x % primes i = 0 x \%\textit{primes}_i=0 x%primesi=0 的时候结束当前标记。
class Solution {
public int countPrimes(int n) {
List<Integer> primes = new ArrayList<Integer>();
boolean[] isComposite = new boolean[n];
for (int i = 2; i < n; ++i) {
if (!isComposite[i]) {
primes.add(i);
}
for (int j = 0; j < primes.size() && i * primes.get(j) < n; ++j) {
isComposite[i * primes.get(j)] = true;
if (i % primes.get(j) == 0)
break;
}
}
return primes.size();
}
}
二进制表示中质数个计算置位
给定两个整数 L 和 R ,找到闭区间 [L, R] 范围内,计算置位位数为质数的整数个数。
(注意,计算置位代表二进制表示中1的个数。例如 21 的二进制表示 10101 有 3 个计算置位。还有,1 不是质数。)
示例 1:
输入: L = 6, R = 10
输出: 4
解释:
6 -> 110 (2 个计算置位,2 是质数)
7 -> 111 (3 个计算置位,3 是质数)
9 -> 1001 (2 个计算置位,2 是质数)
10-> 1010 (2 个计算置位,2 是质数)
示例 2:
输入: L = 10, R = 15
输出: 5
解释:
10 -> 1010 (2 个计算置位, 2 是质数)
11 -> 1011 (3 个计算置位, 3 是质数)
12 -> 1100 (2 个计算置位, 2 是质数)
13 -> 1101 (3 个计算置位, 3 是质数)
14 -> 1110 (3 个计算置位, 3 是质数)
15 -> 1111 (4 个计算置位, 4 不是质数)
遍历计数+哈希集合
class Solution {
public int countPrimeSetBits(int L, int R) {
int[] tmp = {2, 3, 5, 7, 11, 13, 17, 19};
Set<Integer> prime = new HashSet<>() { {
for (int t : tmp)
add(t);
} };
int count = 0;
for (int i = L; i <= R; i++) {
int num = Integer.bitCount(i);
if (prime.contains(num))
count++;
}
return count;
}
}
遍历计数+数组
class Solution {
public int countPrimeSetBits(int L, int R) {
int[] primes = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1};
int count = 0;
for (int i = L; i <= R; i++)
count += primes[Integer.bitCount(i)];
return count;
}
}