leetcode
leetcode 651 ~ 700
二进制表示中质数个计算置位

二进制表示中质数个计算置位

难度:

标签:

题目描述

代码结果

运行时间: 57 ms, 内存: 16.2 MB


/*
 题目思路:
 1. 使用 IntStream 生成从 left 到 right 的数字流。
 2. 使用 Integer.bitCount 计算每个数字的二进制表示中 1 的个数。
 3. 使用过滤器保留计算置位位数为质数的数字。
 4. 使用 count 方法统计满足条件的数字个数。
*/
 
import java.util.stream.IntStream;
 
public class PrimeSetBitsCounterStream {
    public static void main(String[] args) {
        int left = 6, right = 10;
        System.out.println(countPrimeSetBits(left, right)); // 输出 4
    }
 
    public static long countPrimeSetBits(int left, int right) {
        return IntStream.rangeClosed(left, right)
                .filter(num -> isPrime(Integer.bitCount(num)))
                .count();
    }
 
    // 判断一个数是否是质数
    public static boolean isPrime(int num) {
        if (num <= 1) return false;
        for (int i = 2; i * i <= num; i++) {
            if (num % i == 0) return false;
        }
        return true;
    }
}

解释

方法:

该题解通过迭代区间[left, right]中的每个整数,利用内建的bit_count方法计算每个数字的二进制表示中1的个数。随后检查这个计数是否存在于一个预定义的质数集合中。如果存在,说明该整数的计算置位位数是一个质数,因此将这个整数加入到列表nums中。最后,返回列表nums的长度,即为计算置位位数为质数的整数个数。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
你是如何确定质数集合 z 中需要包含哪些数字?是否有可能超过29的质数会影响结果?
质数集合 z 的确定基于二进制表示中可能的最大‘1’的个数。由于一个整数的最大二进制位数限定于该整数的比特长度,对于一般的32位整数,其最大1的个数不会超过32。因此,我们只需考虑小于等于32的质数。在这个题解中,质数集合只列出到29,因为32位整数中1的最大个数为32,而30、31、32都不是质数。如果要处理更大范围的整数,可能需要扩展质数集合至更大的质数。
🦆
题解中提到存储符合条件的整数列表,这种存储方式是否最优?是否有其他不需要存储所有符合条件整数的方法?
题解中存储符合条件的整数列表并不是最优的方式,主要因为这增加了额外的空间需求。更优的方法是直接计数符合条件的整数数量。可以通过设置一个计数器,每当发现一个整数的计算置位为质数时,直接增加这个计数器的值,而不是将整数存入列表。这样可以减少空间消耗,只使用一个整数变量进行计数,从而使算法的空间复杂度从O(n)降低到O(1)。
🦆
在你的算法中,是如何处理边界值,例如left或right为极小或极大值的情况?有没有可能造成整型溢出或性能问题?
在算法中,处理边界值主要依赖于Python的整数类型,它提供了自动的整数扩展功能,可以处理非常大的整数而不会导致整型溢出。对于极小值(如接近0)的处理,Python的整数同样可以很好地处理。但是,如果right非常大,比如接近32位或64位整数的最大值,虽然不会溢出,但是遍历这样广泛的范围可能会造成性能问题,因为算法的时间复杂度与区间[left, right]的大小成线性关系。在实际应用中可能需要对输入范围进行限制或优化算法以处理大范围的数据。

相关问题

位1的个数

编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为汉明重量)。

 

提示:

  • 请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
  • 在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在 示例 3 中,输入表示有符号整数 -3

 

示例 1:

输入:n = 00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。

示例 2:

输入:n = 00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'。

示例 3:

输入:n = 11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'。

 

提示:

  • 输入必须是长度为 32二进制串

 

进阶

  • 如果多次调用这个函数,你将如何优化你的算法?