持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第27天,点击查看活动详情
一、题目描述:
762. 二进制表示中质数个计算置位 - 力扣(LeetCode)
给你两个整数 left 和 right ,在闭区间 [left, right] 范围内,统计并返回 计算置位位数为质数 的整数个数。
计算置位位数 就是二进制表示中 1 的个数。
例如, 21 的二进制表示 10101 有 3 个计算置位。
示例 1:
输入:left = 6, right = 10
输出:4
解释:
6 -> 110 (2 个计算置位,2 是质数)
7 -> 111 (3 个计算置位,3 是质数)
9 -> 1001 (2 个计算置位,2 是质数)
10-> 1010 (2 个计算置位,2 是质数)
共计 4 个计算置位为质数的数字。
示例 2:
输入:left = 10, right = 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 不是质数)
共计 5 个计算置位为质数的数字。
提示:
- 1 <= left <= right <= 10^6
- 0 <= right - left <= 10^4
二、思路分析:
- 暴力法O(N^2):对于每一个数,只要除数i从2开始逐步增加到n-1判断是否能被整除即可。
- 暴力优化O(n\sqrt{n}):i遍历到最大为根号n即可,若能被整除,两个因子若有一个大于根号n,乘积一定小于根号n(反证法) .
- 埃氏筛O(nloglogn) 看下道题的解法
三、AC 代码:
class Solution {
public:
int countPrimes(int n) {
vector<bool> isPrime(n, true); // 小于n的质数数量,为了使得下标与对应元素值一致,n-1个元素需要n个数组
for (int i = 2; i*i <= n-1; ++i) {
if (isPrime[i]) {
/*任意素数x的倍数有:2x, 3x, 4x, ..., x*x, (x+1)*x, ...
任意小于x*x的倍数都被之前的素数筛过滤过,如:2 过滤 2x, 4x, ...,3 过滤 3x, ...
所以从x*x开始过滤之后的倍数,所以x只需遍历到sqrt(N) */
for (int j = i; i*j <= n-1; ++j) {
isPrime[i*j] = false;
}
}
}
int primeNum = 0;
for (int i = 2; i < n; ++i) {
if (isPrime[i]) ++primeNum;
}
return primeNum;
}
};