#191 - Number of 1 Bits
Number of 1 Bits
- Difficulty: Easy
- Topics: Divide and Conquer, Bit Manipulation
- Link: https://leetcode.com/problems/number-of-1-bits/
Problem Description
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.
Constraints:
1 <= n <= 231 - 1
Follow up: If this function is called many times, how would you optimize it?
Solution
1. Problem Deconstruction
Technical Definition
Given a 32-bit unsigned integer n, compute its Hamming weight (cardinality of set bits). The solution must use bitwise operations or optimized string processing to count 1s efficiently.
Beginner Explanation
Convert the number to binary (base-2) and count how many times the digit 1 appears. For example, 5 becomes 101, so the answer is 2.
Mathematical Formulation
Let ,
or equivalently, ,
where .
Constraint Analysis
- :
- Limits binary length to 31 bits (no leading zeros).
- Edge cases: All bits set (31
1s), single-bit numbers (e.g., ). - Excludes zero, so no need to handle empty bitstrings.
2. Intuition Scaffolding
Real-World Metaphor
A parking lot with 32 spaces. Each space has a car (1) or is empty (0). Count occupied spaces by checking each spot or removing cars one by one.
Gaming Analogy
In a dungeon, each enemy (set bit) requires a spell (bitwise AND) to eliminate. The number of casts equals the number of enemies.
Math Analogy
Summing the binary digits of . Equivalent to in computer architecture.
Common Pitfalls
- Infinite Loops for Negative Numbers: Not applicable here (input is positive).
- String Conversion Overhead:
bin(n)in Python is optimized, but bitwise methods avoid string allocation. - Bit Shifting Without Bounds: Unbounded shifts in Python risk infinite loops; limit to 32 iterations.
- Assuming O(n) Time: All solutions are O(1) due to fixed 32-bit length.
- Modulo/Division Inefficiency: Bitwise operations are faster than arithmetic methods.
3. Approach Encyclopedia
Approach 1: Bit Shifting
Pseudocode
def count_bits(n):
count = 0
for _ in range(32):
count += n & 1
n >>= 1
return count
Complexity
- Time: .
- Space: .
Visualization
n = 11 (1011)
Iteration 1: n=1011 → LSB=1, count=1
Iteration 2: n=101 → LSB=1, count=2
Iteration 3: n=10 → LSB=0, count=2
Iteration 4: n=1 → LSB=1, count=3
... (continues for 32 bits)
Approach 2: Brian Kernighan’s Algorithm
Pseudocode
def count_bits(n):
count = 0
while n:
n &= n - 1 # Remove rightmost set bit
count += 1
return count
Complexity
- Time: , = number of set bits (≤31 → ).
- Space: .
Visualization
n = 11 (1011) → 1011 & 1010 = 1010 (count=1)
n = 1010 → & 1001 = 1000 (count=2)
n = 1000 → & 0111 = 0 (count=3)
Approach 3: Binary String Conversion
Pseudocode
def count_bits(n):
return bin(n).count('1')
Complexity
- Time: for string conversion and count.
- Space: for the string (negligible).
4. Code Deep Dive
Optimal Solution (Brian Kernighan’s)
def hammingWeight(n):
count = 0
while n:
n &= n - 1 # Key: Remove rightmost 1
count += 1
return count
Line-by-Line
count = 0: Initialize counter.while n:: Loop until all bits are unset.n &= n - 1: Bitwise AND removes the rightmost1(e.g.,1010 → 1000).count += 1: Increment for each eliminated bit.
Edge Case Handling
- Example 1:
n=11 (1011)→ 3 iterations (3 bits). - Example 2:
n=128 (10000000)→ 1 iteration. - Example 3:
n=2147483645(30 bits) → 30 iterations.
5. Complexity War Room
Hardware-Aware Analysis
- 32-bit operations use minimal CPU cycles (<< 1 ns/op).
- Memory usage: <10 bytes (counter + loop variables).
Industry Comparison
| Method | Time | Space | Readability | Interview Viability |
|---|---|---|---|---|
| Bit Shifting | O(1) | O(1) | 8/10 | ✅ Clear logic |
| Brian Kernighan | O(k) | O(1) | 9/10 | ✅ Optimal & Elegant |
| Binary String | O(1) | O(1) | 10/10 | ✅ Pythonic |
6. Pro Mode Extras
Variants
- LC 338 (Counting Bits for All Numbers): Precompute using DP.
- LC 477 (Total Hamming Distance): Combine bit counts across numbers.
Follow-Up Optimization
Precompute a 256-entry lookup table (byte-wise counts). Split n into 4 bytes and sum:
lookup = [0] * 256
for i in range(256):
lookup[i] = lookup[i // 2] + (i & 1)
def count_bits(n):
return (lookup[n & 0xff] + lookup[(n >> 8) & 0xff] +
lookup[(n >> 16) & 0xff] + lookup[(n >> 24) & 0xff])
Interview Cheat Sheet
- Key Insight: Bitwise AND (
&) and shifts (>>) are your friends. - Mention: Trade-offs between readability (string) and efficiency (bitwise).
- Gotcha: Python handles big integers, but constraints cap at 32 bits.