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?
This problem asks to count the number of set bits (1s) in the binary representation of a given integer. We'll explore two efficient solutions.
This approach cleverly uses bit manipulation to count set bits. The core idea is to repeatedly remove the least significant set bit until no set bits remain.
Algorithm:
ans
to 0.n
is not 0:
n &= n - 1
: This operation clears the least significant set bit in n
. For example, if n
is 6 (binary 110), n - 1
is 5 (binary 101), and the bitwise AND results in 4 (binary 100), effectively removing the rightmost 1.ans += 1
: Increment the counter.ans
.Time Complexity: O(k), where k is the number of set bits in n. In the worst case (n is a power of 2), k is 1. On average, k is log₂(n). This is significantly better than iterating through all bits (O(log₂(n)) in the worst case).
Space Complexity: O(1), as we use only a few constant extra variables.
This solution leverages the property that n & -n
isolates the least significant set bit of n
. Subtracting this bit from n
effectively removes it.
Algorithm:
ans
to 0.n
is not 0:
n -= (n & -n)
: Subtract the least significant set bit from n
.ans += 1
: Increment the counter.ans
.Time Complexity: Same as Solution 1: O(k), where k is the number of set bits.
Space Complexity: O(1).
Code Examples (Python and Java):
Solution 1 (Brian Kernighan's Algorithm):
Python:
class Solution:
def hammingWeight(self, n: int) -> int:
ans = 0
while n:
n &= n - 1
ans += 1
return ans
Java:
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int ans = 0;
while (n != 0) {
n &= n - 1;
++ans;
}
return ans;
}
}
Solution 2 (Using n & -n):
Python:
class Solution:
def hammingWeight(self, n: int) -> int:
ans = 0
while n:
n -= n & -n
ans += 1
return ans
Java:
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int ans = 0;
while (n != 0) {
n -= (n & -n);
++ans;
}
return ans;
}
}
Both solutions are highly efficient for counting set bits, particularly when dealing with numbers having a relatively small number of set bits. The provided code snippets show implementations in various programming languages. The uint32_t
type in C++ ensures that we're treating n
as an unsigned 32-bit integer, handling the problem's constraints correctly. Other languages handle this implicitly or through similar unsigned integer types. The Rust solution directly utilizes the built-in count_ones()
method for optimal efficiency in that language.