LeetCode 762.二进制表示中质数个计算置位(位运算lowbit+质数判断)


题目描述

在这里插入图片描述

在这里插入图片描述

解题思路

枚举 [ left , right ] [\textit{left},\textit{right}] [left,right] 范围内的每个整数,挨个判断是否满足题目要求,对于每个数 x x x需要解决两个问题:

  • 如何求出 x x x的二进制中的 1 1 1的个数?
    1. 库函数Integer.bitCount()
    2. while循环统计 + lowbit操作:x&-x只保留整数 x x x最低位的 1 1 1
  • 如何判断一个数是否为质数?
    1. 枚举 [ 2 , x ] [2,\sqrt{x}] [2,x ]中的每个数 y y y,判断 y y y是否为 x x x的因数,以此来判断一个数是否为质数
    2. 打表:一个 int 的二进制表示不超过 32,可以将 32 以内的质数进行打表
    3. 打表+比特掩码:用一个二进制数 mask = 665772 = 1010001010001010110 0 2 \textit{mask}=665772=10100010100010101100_{2} mask=665772=101000101000101011002 来存储这些质数,其中 mask \textit{mask} mask 二进制的从低到高的第 i i i 位为 1 表示 i i i 是质数,为 0 表示 i i i 不是质数。

代码一:库函数+枚举

class Solution {
    public int countPrimeSetBits(int left, int right) {
        int ans = 0;
        for (int x = left; x <= right; x++) {
            if (isPrime(Integer.bitCount(x))) {
                ans++;
            }
        }
        return ans;
    }
    // 时间复杂度O(Sqrt(x))
    private boolean isPrime(int x) {
        if (x < 2) {
            return false;
        }
        for (int i = 2; i * i <= x; i++) {
            if (x % i == 0) {
                return false;
            }
        }
        return true;
    }
}

Integer.java

public static int bitCount(int i) {
    // HD, Figure 5-2
    i = i - ((i >>> 1) & 0x55555555);
    i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
    i = (i + (i >>> 4)) & 0x0f0f0f0f;
    i = i + (i >>> 8);
    i = i + (i >>> 16);
    return i & 0x3f;
}
  • 时间复杂度: O ( ( right − left ) log ⁡ right ) O((\textit{right}-\textit{left})\sqrt{\log\textit{right}}) O((rightleft)logright )。二进制中 1 的个数为 O ( log ⁡ right ) O(\log\textit{right}) O(logright),判断值为 x x x 的数是否为质数的时间为 O ( x ) O(\sqrt{x}) O(x )

  • 空间复杂度: O ( 1 ) O(1) O(1)

代码二:lowbit+打表

class Solution {
    public int countPrimeSetBits(int left, int right) {
        int ans = 0;
        int[] primes = new int[]{2,3,5,7,11,13,17,19,23,29,31};
        boolean[] hash = new boolean[32];
        for (int p : primes) {
            hash[p] = true;
        }
        for (int x = left; x <= right; x++) {
            if (hash[countBit(x)]) {
                ans++;
            }
        }
        return ans;    
    }
	// 时间复杂度O(log x)
    private int countBit(int x) {
        int cnt = 0;
        while (x != 0) {
            x -= (x & -x);
            cnt++;
        }
        return cnt;
    }
}
  • 时间复杂度: O ( ( r i g h t − l e f t ) × log ⁡ r i g h t ) O((right - left) \times \log{right}) O((rightleft)×logright)

  • 空间复杂度: O ( C ) O(C) O(C)

代码三:库函数+比特掩码

class Solution {
    public int countPrimeSetBits(int left, int right) {
        int ans = 0;
        for (int x = left; x <= right; ++x) {
            if (((1 << Integer.bitCount(x)) & 665772) != 0) {
                ++ans;
            }
        }
        return ans;
    }
}
  • 时间复杂度: O ( right − left ) O(\textit{right}-\textit{left}) O(rightleft)

  • 空间复杂度: O ( 1 ) O(1) O(1)

Reference

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xylitolz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值