762、二进制表示中质数个计算置位
给你两个整数 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 个计算置位为质数的数字。
思路:
循环遍历找出每个数的计算置位,然后判断是否是质数
class Solution:
# 计算置位
# python3.10之后int有bit_count方法用于计算二进制数字中1的个数
def bit_count(self, num):
i = 1
count = 0
while i < num:
if i & num: count += 1
i <<= 1
return count
# 判断是否是质数
def is_prime(self, num):
if num < 2: return False
i = 2
while i * i <= num:
if num % i == 0:
return False
i += 1
return True
def countPrimeSetBits(self, left: int, right: int) -> int:
return sum(self.is_prime(self.bit_count(i)) for i in range(left, right + 1))
根据题目给出的数据大小,最多不会超过10**6,那么转换成二进制也就是最多会出现20个1的情况,
这里可以对判断质数进行优化
class Solution:
# 缓存1到20之间的质数
def __init__(self):
self.primes = {i for i in range(20) if self.is_prime(i)}
···省略
def countPrimeSetBits(self, left: int, right: int) -> int:
return sum(self.bit_count(i) in self.primes for i in range(left, right + 1))
这里使用集合来存储质数,其实还可以用二进制位的方式代表,我们知道20以内的质数有{2, 3, 5, 7, 11, 13, 17, 19},那么将之转换成二进制,比如2为质数,那么将二进制位第二位(最低位是0)设置1,也就是设置取2**2,这样就可以标记每个质数所在的位置。
那么最后得出的二进制数为:10100010100010101100,其代表的十进制数为665772
要想判断计算置位是不是质数,只需要对计算置位进行左移即可,判断对应位置是否是1即可
class Solution:
# python3.10之后int有bit_count方法用于计算二进制数字中1的个数
···省略
def countPrimeSetBits(self, left: int, right: int) -> int:
return sum((1 << self.bit_count(i)) & 665772 != 0 for i in range(left, right + 1))
这个665772也可以自己计算
total = sum(1 << i for i in range(20) if self.is_prime(i))
print(total, bin(total))