← 返回题目列表

置位位数为质数的整数个数如何用位运算统计?

简单 第 24 / 26 题 更新于 2026/08/01
位运算质数汉明重量计数

简化版

遍历区间 [left,right],对每个数统计二进制中 1 的个数,再判断这个个数是否为质数。由于整数范围通常不大,1 的个数最多 32,可以用质数集合或位掩码快速判断。

详细版

统计 1 的个数可以用内置函数 Integer.bitCount(x),也可以用 x &= x-1 手写。对 32 位整数,可能的置位数量只有 0 到 32,其中质数是 2,3,5,7,11,13,17,19,23,29,31

时间复杂度为 O((right-left+1) * 位数),若用内置 bitCount 可视作常数。面试重点是区分“数字本身是否为质数”和“数字的 1 的个数是否为质数”。

完整版教学

一、题目判断的是谁为质数

题目不是问数字 x 是否为质数,而是问 x 的二进制中 1 的数量是否为质数。

x = 10
二进制 1010
1 的个数 = 2
2 是质数,所以 10 计入答案

这个语义如果读错,整题就会跑偏。

二、如何统计置位位数

置位位数也叫汉明重量。可以用内置函数:

Integer.bitCount(x)

也可以手写:

while x != 0:
    x = x & (x - 1)
    count++

x & (x-1) 每次会消掉最低位的 1。

三、哪些 count 是质数

对 32 位整数,count 最大也就 32。质数集合很小:

count是否质数
0
1
2
3
4
5

记忆钩子:这题质数判断的对象是 bitCount,范围很小,可以预处理。

可以用 Set<Integer>,也可以用一个整数位掩码记录哪些 count 是质数。

四、代码模板

int countPrimeSetBits(int left, int right) {
    Set<Integer> primes = Set.of(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31);
    int ans = 0;
    for (int x = left; x <= right; x++) {
        if (primes.contains(Integer.bitCount(x))) {
            ans++;
        }
    }
    return ans;
}

这份写法可读性最好。若面试追求位味,可以把质数集合压成一个 mask。

五、质数集合也能用位掩码

构造:

primeMask = 0
对每个质数 p:primeMask |= 1 << p

判断:

((primeMask >> count) & 1) == 1

这种写法把“count 是否在质数集合中”也变成了位查询。

六、用例子推演

left=6,right=10

6  = 110  => count=2 => 计入
7  = 111  => count=3 => 计入
8  = 1000 => count=1 => 不计
9  = 1001 => count=2 => 计入
10 = 1010 => count=2 => 计入

答案是 4。

七、常见误区与追问

  • 误区:判断 x 本身是否为质数。 题目判断的是 bitCount(x)
  • 误区:把 1 当成质数。 1 不是质数。
  • 误区:忘记 0 也不是质数。 没有 1 的数字不应计入。
  • 追问:为什么质数集合这么小? 32 位整数最多只有 32 个 1。
  • 追问:能不用内置函数吗? 可以用 x & (x-1) 手写计数。
  • 追问:复杂度是多少? 遍历区间,单个数字统计为常数位数。

八、加强记忆

置位质数题分两步:先数 1,再判这个数量是不是质数。不要去判断数字本身。Integer.bitCount 是工程写法,x&(x-1) 是面试解释位技巧;质数集合只到 31,很小,Set 或 bitmask 都可以。