刷题笔记-762. 二进制表示中质数个计算置位

150 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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

二、思路分析:

  1. 暴力法O(N^2):对于每一个数,只要除数i从2开始逐步增加到n-1判断是否能被整除即可。
  2. 暴力优化O(n\sqrt{n}):i遍历到最大为根号n即可,若能被整除,两个因子若有一个大于根号n,乘积一定小于根号n(反证法) .
  3. 埃氏筛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;
    }
};