Given a positive integer n, write a function that returns the number of set bits in its binary representation (also known as the Hamming weight).
Example 1:
Input: n = 11
Output: 3
Explanation:
The input binary string 1011 has a total of three set bits.Example 2:
Input: n = 128
Output: 1
Explanation:
The input binary string 10000000 has a total of one set bit.Example 3:
Input: n = 2147483645
Output: 30
Explanation:
The input binary string 1111111111111111111111111111101 has a total of thirty set bits.I've solved this problem using two methods:
-
Method 1: Modulo and Division
-
We repeatedly divide
nby2and add1to the result each time we encounter an odd number (i.e.,n % 2 == 1, which means the least significant bit is1). -
Code
def hammingWeight_method1(self, n: int) -> int: res = 0 while n: res += n % 2 n = n // 2 return res
-
Step-by-Step Walkthrough (n = 11)
-
Binary representation of 11 is:
1011Iteration n n % 2 res Updated n 1 11 1 1 5 2 5 1 2 2 3 2 0 2 1 4 1 1 3 0 -
Final result:
res = 3
-
-
-
Method 2: Brian Kernighan’s Algorithm (Optimized Bit Manipulation)
-
This method subtracts
1fromnand performsn = n & (n-1)in each iteration. This clears the rightmost set bit. We incrementresfor every operation untilnbecomes0. -
Code
def hammingWeight_method2(self, n: int) -> int: res = 0 while n: n &= (n - 1) res += 1 return res
-
Step-by-Step Walkthrough (n = 11)
-
Binary representation of 11 is:
1011Iteration n (binary) n-1 (binary) n & (n-1) result res 1 1011 (11) 1010 (10) 1010 (10) 1 2 1010 (10) 1001 (9) 1000 (8) 2 3 1000 (8) 0111 (7) 0000 (0) 3 -
Final result:
res = 3
-
-
-
Method 1: Simple and Easy to Understand
- This method mimics converting a number to binary and counting the
1s. - It is intuitive and works well for learning the concept of bitwise operations.
- However, it processes all bits even if most of them are zero.
- This method mimics converting a number to binary and counting the
-
Method 2: Efficient and Optimized
- Brian Kernighan’s method is significantly faster for sparse bit representations.
- It only loops for the number of set bits.
- Ideal for large integers with fewer set bits.
| Method | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Modulo & Division | O(1) | O(1) | Maximum 32 iterations (since n is a 32-bit integer). |
| Brian Kernighan's Method | O(1) | O(1) | At most 32 iterations; faster in practice when n has fewer set bits. |
Given an integer n, return an array ans of length n + 1 such that for each i (0 <= i <= n), ans[i] is the number of 1's in the binary representation of i.
Example 1:
Input: n = 2
Output: [0,1,1]
Explanation:
0 --> 0
1 --> 1
2 --> 10Example 2:
Input: n = 5
Output: [0,1,1,2,1,2]
Explanation:
0 --> 0
1 --> 1
2 --> 10
3 --> 11
4 --> 100
5 --> 101- Efficiency: Instead of calculating set bits from scratch for every number, I've used a previously computed result to compute the current result in constant time.
- Optimal Substructure: If we know the number of 1's in a number
i, then we can use that to compute the result of a number derived fromiusing powers of 2. - Avoids Repeated Computation: Reduces redundancy by reusing answers we’ve already computed.
For any number i:
-
Let
offsetbe the largest power of 2 less than or equal toi. -
Then:
countBits[i] = 1 + countBits[i - offset]Why? Because:offsethas exactly one set bit.i - offsethas already been computed and stored.
-
Initialization
- We define an array
dpof sizen + 1initialized to all0s. - The variable
offsetis used to keep track of the current power of two. - Start with
offset = 1.
- We define an array
We want to compute the number of 1 bits in binary representation of all numbers from 0 to 5.
-
Initialization:
dp = [0, 0, 0, 0, 0, 0] # size = 6 offset = 1
-
Iteration 1:
i = 1-
offset * 2 = 2 != i→ no change in offset -
dp[1] = 1 + dp[1 - 1] = 1 + dp[0] = 1dp = [0, 1, 0, 0, 0, 0]
-
-
Iteration 2:
i = 2-
offset * 2 = 2 == i→ updateoffset = 2 -
dp[2] = 1 + dp[2 - 2] = 1 + dp[0] = 1dp = [0, 1, 1, 0, 0, 0]
-
-
Iteration 3:
i = 3-
offset * 2 = 4 != i -
dp[3] = 1 + dp[3 - 2] = 1 + dp[1] = 2dp = [0, 1, 1, 2, 0, 0]
-
-
Iteration 4:
i = 4-
offset * 2 = 4 == i→ updateoffset = 4 -
dp[4] = 1 + dp[4 - 4] = 1 + dp[0] = 1dp = [0, 1, 1, 2, 1, 0]
-
-
Iteration 5:
i = 5-
offset * 2 = 8 != i -
dp[5] = 1 + dp[5 - 4] = 1 + dp[1] = 2dp = [0, 1, 1, 2, 1, 2]
-
-
Final Output
[0, 1, 1, 2, 1, 2]
| Method | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| DP with Offset Optimization | Each element is computed once using previously known values. |
- Avoids Bitwise Operations Per Number: Traditional methods might require
O(log i)operations perito count bits. - Uses Precomputed Results: Every new result builds directly on a smaller result with a single additional
1bit. - Linear Time: Every number is processed exactly once in the loop.
- Scalable: Can handle large values of
nefficiently up to the constraint limits.
Reverse bits of a given 32 bits unsigned integer.
Note:
Note that in some languages, such as Java, there is no unsigned integer type. In this case, both input and output will be given as a signed integer type. They should not affect your implementation, as the integer's internal binary representation is the same, whether it is signed or unsigned.
In Java, the compiler represents the signed integers using 2's complement notation. Therefore, in Example 2 above, the input represents the signed integer -3 and the output represents the signed integer -1073741825.
Example 1:
Input: n = 00000010100101000001111010011100
Output: 964176192 (00111001011110000010100101000000)
Explanation: The input binary string 00000010100101000001111010011100 represents the unsigned integer 43261596, so return 964176192 which its binary representation is 00111001011110000010100101000000.Example 2:
Input: n = 11111111111111111111111111111101
Output: 3221225471 (10111111111111111111111111111111)
Explanation: The input binary string 11111111111111111111111111111101 represents the unsigned integer 4294967293, so return 3221225471 which its binary representation is 10111111111111111111111111111111.We need to reverse the bits of a number. That is, bit at position 0 becomes bit at position 31, bit at position 1 becomes bit at position 30, and so on.
To achieve this, we follow these steps:
-
Initialize result
res = 0 -
Loop for all 32 bits
i = 0to31:- Extract the
i-thbit fromnusing:(n >> i) & 1 - Place that bit in the
(31 - i)-th position inres:res = res | (bit << (31 - i))
- Extract the
-
Return the final
res
-
Let’s dry-run the solution for:
n = 43261596 # Binary: 00000010100101000001111010011100
-
We initialize:
res = 0 -
We loop from i = 0 to 31:
Iteration (i) Extracted Bit (n >> i) & 1New Bit Position in res(31 - i)res(in binary)0 0 31 00000000000000000000000000000000 1 0 30 00000000000000000000000000000000 2 1 29 00100000000000000000000000000000 3 1 28 00110000000000000000000000000000 4 1 27 00111000000000000000000000000000 5 0 26 00111000000000000000000000000000 6 0 25 00111000000000000000000000000000 7 1 24 00111001000000000000000000000000 8 0 23 00111001000000000000000000000000 9 1 22 00111001010000000000000000000000 10 0 21 00111001010000000000000000000000 11 1 20 00111001010100000000000000000000 12 0 19 00111001010100000000000000000000 13 0 18 00111001010100000000000000000000 14 1 17 00111001010101000000000000000000 15 0 16 00111001010101000000000000000000 16 0 15 00111001010101000000000000000000 17 0 14 00111001010101000000000000000000 18 0 13 00111001010101000000000000000000 19 1 12 00111001010101000100000000000000 20 0 11 00111001010101000100000000000000 21 1 10 00111001010101000101000000000000 22 0 9 00111001010101000101000000000000 23 0 8 00111001010101000101000000000000 24 0 7 00111001010101000101000000000000 25 0 6 00111001010101000101000000000000 26 0 5 00111001010101000101000000000000 27 0 4 00111001010101000101000000000000 28 0 3 00111001010101000101000000000000 29 0 2 00111001010101000101000000000000 30 0 1 00111001010101000101000000000000 31 0 0 00111001010101000101000000000000 -
Final binary value:
00111001011110000010100101000000Decimal value:964176192 -
This matches the expected output.
| Metric | Value | Explanation |
|---|---|---|
| Time Complexity | Always runs for 32 iterations regardless of input | |
| Space Complexity | No extra space used except constant-size variables |
- Bit manipulation is the most efficient and direct way to reverse binary digits.
- Other approaches (e.g., converting to a string, reversing, and parsing) are less performant and use extra space.
- This approach guarantees constant time and space, which is optimal for fixed 32-bit integer problems.
- Use
bit = (n >> i) & 1to extract thei-thbit from a number. - Use
res = res | (bit << (31 - i))to place the bit at its reversed position. - Think in terms of bit positions rather than number values when working with bit-level problems.
Given an array nums containing n distinct numbers in the range [0, n], return the only number in the range that is missing from the array.
Example 1:
Input: nums = [3,0,1]
Output: 2
Explanation:
n = 3 since there are 3 numbers, so all numbers are in the range [0,3]. 2 is the missing number in the range since it does not appear in nums.Example 2:
Input: nums = [0,1]
Output: 2
Explanation:
n = 2 since there are 2 numbers, so all numbers are in the range [0,2]. 2 is the missing number in the range since it does not appear in nums.Example 3:
Input: nums = [9,6,4,2,3,5,7,0,1]
Output: 8
Explanation:
n = 9 since there are 9 numbers, so all numbers are in the range [0,9]. 8 is the missing number in the range since it does not appear in nums.I've implemented two efficient approaches to solve this problem:
-
Approach 1: Mathematical Sum Formula
-
The sum of first
nnatural numbers:$$ \text{expected_sum} = \frac{n \cdot (n + 1)}{2} $$
-
Subtract the actual sum of elements in the array from the expected sum:
$$ \text{missing_number} = \text{expected_sum} - \text{actual_sum} $$
-
But I've used an optimized way:
$$ res = n + (0 - nums[0]) + (1 - nums[1]) + \dots + (n-1 - nums[n-1]) $$
-
-
Approach 2: Bit Manipulation (Using XOR)
-
XOR of a number with itself is 0:
x ^ x = 0 -
XOR of a number with 0 is the number itself:
x ^ 0 = x -
XOR all numbers from 0 to n with all elements in the array:
$$ \text{missing} = (0 \oplus 1 \oplus 2 \dots \oplus n) \oplus (\text{nums[0]} \oplus \text{nums[1]} \oplus \dots) $$
-
All matching numbers cancel out, leaving only the missing number.
-
-
We’ll use Example 3:
nums = [9,6,4,2,3,5,7,0,1] Expected Output: 8
-
Walkthrough for Method 1 (Mathematical)
-
Initial:
res = len(nums) = 9Iteration (i) nums[i] i - nums[i] res updated 0 9 0 - 9 = -9 9 + (-9) = 0 1 6 1 - 6 = -5 0 + (-5) = -5 2 4 2 - 4 = -2 -5 + (-2) = -7 3 2 3 - 2 = 1 -7 + 1 = -6 4 3 4 - 3 = 1 -6 + 1 = -5 5 5 5 - 5 = 0 -5 + 0 = -5 6 7 6 - 7 = -1 -5 + (-1) = -6 7 0 7 - 0 = 7 -6 + 7 = 1 8 1 8 - 1 = 7 1 + 7 = 8 -
Final Answer: 8
-
-
Walkthrough for Method 2 (Bit Manipulation using XOR)
-
Initial:
n = 9 xorr = 9Iteration (i) nums[i] i ^ nums[i] xorr (updated) 0 9 0 ^ 9 = 9 9 ^ 9 = 0 1 6 1 ^ 6 = 7 0 ^ 7 = 7 2 4 2 ^ 4 = 6 7 ^ 6 = 1 3 2 3 ^ 2 = 1 1 ^ 1 = 0 4 3 4 ^ 3 = 7 0 ^ 7 = 7 5 5 5 ^ 5 = 0 7 ^ 0 = 7 6 7 6 ^ 7 = 1 7 ^ 1 = 6 7 0 7 ^ 0 = 7 6 ^ 7 = 1 8 1 8 ^ 1 = 9 1 ^ 9 = 8 -
Final Answer: 8
-
| Approach | Time Complexity | Space Complexity | Explanation |
|---|---|---|---|
| Method 1 (Sum) | Single loop of size n, constant space |
||
| Method 2 (XOR) | Single loop with XORs, constant space |
-
Method 1:
- Avoids sorting or extra memory
- Constant-time arithmetic inside loop
- No need for a full sum formula if prone to overflow
-
Method 2:
- XOR operation is extremely fast and lightweight
- No risk of integer overflow (which can happen with sum formula)
- Cancels out duplicates naturally, finding the missing number efficiently