762. Prime Number of Set Bits in Binary Representation
Problem Description
The problem provides us with two integers, left
and right
, and asks us to calculate how many numbers in the range from left
to right
(inclusive) have a prime number of set bits in their binary representations. The term "set bits" refers to the number of 1’s that appear in the binary form of a given number. For example, the number 21
has a binary representation of 10101
, which contains three 1’s, or three set bits.
Intuition
The intuition behind the solution can be broken down into a few logical steps:
-
Identify the Prime Numbers: Since we are interested in numbers that have a prime number of set bits, we first need a set of prime numbers to check against. However, we don't need all prime numbers, just the ones within the possible range of set bits for numbers in our input range. Given that the max value for a 32-bit integer is 2^31 - 1, it has at maximum 31 set bits. The prime numbers within this range are
{2, 3, 5, 7, 11, 13, 17, 19}
. -
Count Set Bits: For each number in the inclusive range between
left
andright
, we need to determine the number of set bits. There is a built-in method in Python calledbit_count
for integers that do just that, counting the number of bits set to1
in binary representation. -
Check Primes: Once we have the count of set bits for a number, we check if this count is in our pre-identified set of prime numbers.
-
Summing Up Prime Set Bits Counts: Finally, we need to sum up how many numbers fall within our criteria. This is done using sum comprehension in Python, where for each number in our range, we count it only if the number of set bits is a prime number.
By combining these steps, we are able to arrive at the final count efficiently.
Learn more about Math patterns.
Solution Approach
The implementation of the solution uses a simple but effective approach:
-
Define a Set of Prime Numbers:
- We create a set called
primes
which contains the prime numbers less than 20 (as calculated above, since 32-bit integers have a maximum of 31 set bits, and 19 is the largest prime number less than 31). - The set data structure is chosen due to its O(1) time complexity for membership checking, as we will need to check if a count (number of set bits) is a prime number.
- We create a set called
-
Iterate Over the Range:
- We loop over each number from
left
toright
(inclusive) using a range in the loop:for i in range(left, right + 1)
. - This iteration is simple and direct, covering each integer in the provided range.
- We loop over each number from
-
Count the Set Bits:
- For each number
i
in the range, we use thebit_count()
method to find the number of set bits for that number. - The use of
bit_count()
is a Python-specific method introduced in version 3.10 which simplifies and optimizes the operation of counting set bits.
- For each number
-
Check for Prime Number of Set Bits:
- The comprehension part
i.bit_count() in primes
checks if the number of set bits is in our set of prime numbers. - If the number of set bits is a prime number, this evaluates to
True
, which, when summed using thesum()
function, is treated as1
.
- The comprehension part
-
Calculate the Total Count:
- Finally, the
sum()
function adds up all the1
s (for eachTrue
result) reflecting the count of numbers that satisfy the condition (having a prime number of set bits).
- Finally, the
The entire operation returns the sum, which is precisely the count of numbers with a prime number of set bits in the specified range. This approach is efficient because it minimizes the calls to check for prime numbers by predefining the possible primes and uses bitwise operation optimized functions for count calculation.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's take the range from left = 10
to right = 15
and illustrate the solution approach step by step.
-
Define the Set of Prime Numbers: We have a pre-determined set of prime numbers, which are
{2, 3, 5, 7, 11, 13, 17, 19}
because we are working within the 32-bit integer range. -
Iterate Over the Range: We review the numbers 10, 11, 12, 13, 14, and 15.
-
Count the Set Bits and Check for Prime Number of Set Bits:
- For the number
10
which in binary is1010
, there are two set bits. Two is a prime number. - For the number
11
which in binary is1011
, there are three set bits. Three is also a prime number. - For the number
12
which in binary is1100
, there are two set bits. Two is a prime number. - For the number
13
which in binary is1101
, there are three set bits. Three is a prime number. - For the number
14
which in binary is1110
, there are three set bits. Three is a prime number. - For the number
15
which in binary is1111
, there are four set bits. Four is not a prime number.
- For the number
-
Calculate the Total Count: Out of the numbers from 10 to 15:
- Four numbers (
10
,11
,12
,13
,14
) have a prime number of set bits. - Two numbers (
15
) do not.
- Four numbers (
Therefore, the final count of numbers with a prime number of set bits between 10 and 15, inclusive, is 4.
Solution Implementation
1class Solution:
2 def count_prime_set_bits(self, left: int, right: int) -> int:
3 # Define a set of prime numbers that could represent set bit counts
4 primes = {2, 3, 5, 7, 11, 13, 17, 19}
5
6 # Use list comprehension to count the number of integers in the specified range
7 # which have a prime number of set bits (1s in their binary representation)
8 prime_set_bits_count = sum(
9 bin(i).count('1') in primes
10 for i in range(left, right + 1)
11 )
12
13 return prime_set_bits_count
14
1import java.util.Set;
2
3class Solution {
4 // Initialization of a Set containing prime numbers.
5 private static final Set<Integer> PRIME_NUMBERS = Set.of(2, 3, 5, 7, 11, 13, 17, 19);
6
7 // Method to count the numbers in the given range with a prime number of set bits.
8 public int countPrimeSetBits(int left, int right) {
9 // Initialize a counter for the numbers meeting the criteria.
10 int primeSetBitsCount = 0;
11
12 // Iterate over the range from left to right, inclusive.
13 for (int i = left; i <= right; ++i) {
14 // Use Integer.bitCount to determine the number of set bits in the binary representation of 'i'.
15 // If the number of set bits is in the PRIME_NUMBERS set, increment the counter.
16 if (PRIME_NUMBERS.contains(Integer.bitCount(i))) {
17 primeSetBitsCount++;
18 }
19 }
20
21 // Return the total count of numbers with a prime number of set bits.
22 return primeSetBitsCount;
23 }
24}
25
1#include <unordered_set>
2
3class Solution {
4public:
5 // Function to count the number of integers within a range [left, right]
6 // that have a prime number of set bits in their binary representation
7 int countPrimeSetBits(int left, int right) {
8 // Define a set of primes that are less than or equal to 19, since the maximum
9 // number of bits for an int (32 bits) has at most 19 set bits to be a prime.
10 std::unordered_set<int> primeSet{2, 3, 5, 7, 11, 13, 17, 19};
11
12 int count = 0; // This variable will store the count of numbers satisfying the condition
13
14 // Iterate over each number in the given range
15 for (int i = left; i <= right; ++i) {
16 // Use __builtin_popcount to count the number of set bits in the current number
17 // Increase the count if the number of set bits is in the primeSet
18 count += primeSet.count(__builtin_popcount(i));
19 }
20
21 // Return the final count
22 return count;
23 }
24};
25
1// Define a set of prime numbers less than or equal to 19
2const primeSet: Set<number> = new Set([2, 3, 5, 7, 11, 13, 17, 19]);
3
4// Function to count the number of integers within a range [left, right]
5// that have a prime number of set bits in their binary representation.
6function countPrimeSetBits(left: number, right: number): number {
7 let count = 0; // Initialize count of numbers satisfying the condition
8
9 // Iterate over each number within the range from left to right inclusive
10 for (let i = left; i <= right; i++) {
11 // Count the number of set bits (1s) in the binary representation of the number
12 const setBits = countSetBits(i);
13
14 // If the number of set bits is prime, increment the count
15 if (primeSet.has(setBits)) {
16 count++;
17 }
18 }
19
20 // Return the final count
21 return count;
22}
23
24// Helper function to count the number of set bits in the binary representation of a number
25function countSetBits(num: number): number {
26 let setBits = 0; // Initialize count of set bits to 0
27
28 while (num > 0) {
29 setBits += num & 1; // Increment setBits if the least significant bit is 1
30 num >>= 1; // Right shift the number to check the next bit
31 }
32
33 return setBits;
34}
35
Time and Space Complexity
Time Complexity
The time complexity of the given code is mainly determined by the for loop, which iterates from left
to right
inclusive.
We let N
represent the number of integers in the range [left, right]
, then N
equals right - left + 1
.
For each i
in the range [left, right]
, we calculate the number of set bits using i.bit_count()
. Since the maximum number of bits for an integer is bounded by the logarithm of the integer, let's denote the number of bits as k
. The operation bit_count()
has a time complexity of O(k)
.
However, since the values of left
and right
are not restricted by input size as in traditional algorithm analyses, where N
would normally depend on some input parameter like array size, defining k
is trickier. Generally, for a 32-bit integer, k
would be at most 32
. Thus we can consider bit_count()
operation to be O(1)
for practical purposes.
Therefore, since bit_count()
takes constant time and is called N
times, the time complexity of the entire loop is O(N)
.
The set membership test in primes
is O(1)
because lookup in a set of prime numbers (of fixed small size) is constant time.
Combining these, the loop has a time complexity of O(N * 1) = O(N)
.
Space Complexity
The space complexity of the given code is low.
We have a set, primes
, containing a fixed number of prime numbers which is independent of the input size. This means it consumes a constant amount of space, O(1)
.
The temporary variables for the loop and the sum operation are also constant space, so they do not contribute to the space complexity in terms of N
.
Therefore, the overall space complexity of the code is O(1)
.
Learn more about how to find time and space complexity quickly using problem constraints.
Which technique can we use to find the middle of a linked list?
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
LeetCode Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way we
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Want a Structured Path to Master System Design Too? Don’t Miss This!