Count Set Bits Brian Kernighan Algorithm in DSA Go - Time & Space Complexity
We want to understand how fast the Brian Kernighan algorithm counts the number of 1s in a number's binary form.
How does the time taken grow as the number gets bigger?
Analyze the time complexity of the following code snippet.
func countSetBits(n int) int {
count := 0
for n > 0 {
n = n & (n - 1)
count++
}
return count
}
This code counts how many bits are set to 1 in the binary form of the number n using Brian Kernighan's method.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The loop runs and clears the rightmost set bit each time.
- How many times: The loop runs once for each set bit in n.
Each loop iteration removes one set bit, so the number of operations depends on how many 1s are in n.
| Input Size (n) | Approx. Operations (set bits) |
|---|---|
| 10 (binary 1010) | 2 |
| 100 (binary 1100100) | 3 |
| 1000 (binary 1111101000) | 6 |
Pattern observation: The time grows with the number of set bits, not the total bits or value size.
Time Complexity: O(k) where k is the number of set bits in n.
This means the algorithm runs faster when there are fewer 1s, and slower when there are more 1s in the number.
[X] Wrong: "The loop runs for all bits in the number, so it is O(log n)."
[OK] Correct: The loop only runs once per set bit, not for every bit position, so it depends on the count of 1s, not total bits.
Knowing this algorithm helps you show efficient bit manipulation skills, which are often appreciated in coding interviews.
What if we changed the input to always have only one set bit? How would the time complexity change?
Practice
Solution
Step 1: Understand the algorithm's main operation
The Brian Kernighan algorithm clears the least significant set bit by doing n = n & (n-1) repeatedly.Step 2: Effect of clearing bits
Each operation removes one '1' bit, counting how many set bits exist until n becomes zero.Final Answer:
It repeatedly clears the least significant set bit until the number becomes zero -> Option AQuick Check:
Clearing bits counts set bits [OK]
- Counting total bits instead of set bits
- Using string conversion instead of bitwise operations
- Shifting without checking bits
n?Solution
Step 1: Identify the Brian Kernighan loop condition
The loop runs while n is not zero, clearing the least significant set bit each iteration.Step 2: Confirm the bit clearing operation
The operation n = n & (n - 1) clears the least significant set bit correctly.Final Answer:
for n != 0 { count++; n = n & (n - 1) } -> Option CQuick Check:
Loop with n & (n-1) clears bits [OK]
- Using shift instead of bit clear
- Using while instead of for in Go
- Counting bits by subtracting 1 only
func countSetBits(n int) int {
count := 0
for n != 0 {
n = n & (n - 1)
count++
}
return count
}
fmt.Println(countSetBits(13))Solution
Step 1: Convert 13 to binary
13 in binary is 1101, which has three set bits (1s).Step 2: Apply Brian Kernighan algorithm
Each iteration clears one set bit, so count increments 3 times until n becomes 0.Final Answer:
3 -> Option BQuick Check:
Binary 1101 has 3 ones [OK]
- Counting total bits instead of set bits
- Miscounting binary digits
- Confusing bitwise AND with OR
func countSetBits(n int) int {
count := 0
for n > 0 {
count = count + (n & 1)
n = n & (n - 1)
}
return count
}Solution
Step 1: Analyze counting method
The code adds n & 1 to count, which checks the least significant bit.Step 2: Analyze bit clearing step
Then it clears the least significant set bit with n = n & (n - 1), which may skip bits.Step 3: Conflict explanation
Using both methods together causes incorrect counting because n & 1 and clearing bits are mixed incorrectly.Final Answer:
Using n & 1 to count bits conflicts with n = n & (n - 1) clearing bits -> Option AQuick Check:
Mixing bit check and clear causes wrong count [OK]
- Mixing bitwise AND with bit clearing
- Incorrect loop condition
- Wrong initialization of count
[7, 8, 15, 23], which Go code snippet correctly uses Brian Kernighan's algorithm to return a map of each integer to its count of set bits?Solution
Step 1: Check countSetBits function correctness
func countSetBits(n int) int { count := 0 for n != 0 { n = n & (n - 1) count++ } return count } func mapSetBits(nums []int) map[int]int { result := make(map[int]int) for _, num := range nums { result[num] = countSetBits(num) } return result } uses Brian Kernighan's algorithm correctly to count set bits.Step 2: Check mapSetBits function logic
The mapSetBits function correctly maps each number (as key) to its set bit count (as value).Step 3: Verify other options
func countSetBits(n int) int { count := 0 for n > 0 { count += n & 1 n = n >> 1 } return count } func mapSetBits(nums []int) map[int]int { result := make(map[int]int) for i := 0; i < len(nums); i++ { result[i] = countSetBits(nums[i]) } return result } uses shift method and wrong map keys; func countSetBits(n int) int { count := 0 for n != 0 { n = n & (n - 1) count++ } return count } func mapSetBits(nums []int) map[int]int { result := make(map[int]int) for i, num := range nums { result[i] = countSetBits(num) } return result } uses index as key; func countSetBits(n int) int { count := 0 for n != 0 { n = n & (n - 1) count++ } return count } func mapSetBits(nums []int) map[int]int { result := make(map[int]int) for _, num := range nums { result[countSetBits(num)] = num } return result } reverses key and value.Final Answer:
The code that maps num to countSetBits(num) -> Option DQuick Check:
Map keys are numbers, values are counts [OK]
- Using index as map key instead of number
- Swapping keys and values in map
- Using shift method instead of Brian Kernighan
Ready to prove it?
Pass the test and this pattern moves unknown
