29. Count Set Bits
β GFG solution to the Count Set Bits problem: find total count of set bits from 1 to n using mathematical pattern recognition and bit manipulation. π
The problem can be found at the following link: π Question Link
π§© Problem Description
You are given a number n. Find the total count of set bits for all numbers from 1 to n (both inclusive).
A set bit refers to a bit in the binary representation of a number that is 1. The task is to efficiently count all such bits across the entire range.
π Examples
Example 1
Input: n = 4
Output: 5
Explanation: For numbers from 1 to 4:
- 1: 0 0 1 => 1 set bit
- 2: 0 1 0 => 1 set bit
- 3: 0 1 1 => 2 set bits
- 4: 1 0 0 => 1 set bit
Therefore, the total set bits are 1 + 1 + 2 + 1 = 5.Example 2
π Constraints
$1 \le n \le 10^8$
β
My Approach
The optimal approach uses Mathematical Pattern Recognition with Bit Manipulation to efficiently count set bits:
Recursive Pattern Recognition
Mathematical Insight:
For any number n, we can find the highest power of 2 less than or equal to n (let's call it 2^x).
Count set bits in three parts:
Full pattern from 0 to (2^x - 1)
Contribution of the most significant bit from 2^x to n
Remaining set bits after removing the highest bit
Pattern Formula:
For numbers from 0 to (2^x - 1): Total set bits = x * 2^(x-1)
This is because each bit position i (0 to x-1) is set exactly 2^(x-1) times
MSB contribution from 2^x to n: (n - 2^x + 1) times the MSB is set
Recursive Strategy:
Find highest bit position x using log2(n)
Calculate full pattern bits: x * 2^(x-1)
Calculate MSB contribution: (n - 2^x + 1)
Recursively solve for remaining: countSetBits(n - 2^x)
Base Case:
If n == 0, return 0
This ensures termination of recursion
Optimization:
Using bit operations (1 << x instead of pow(2, x)) for faster computation
Logarithmic recursion depth ensures efficient performance
π Time and Auxiliary Space Complexity
Expected Time Complexity: O(log n), as we recursively process the number by removing the highest bit in each step, leading to logarithmic depth recursion.
Expected Auxiliary Space Complexity: O(log n), due to the recursion stack space. Each recursive call processes a smaller subproblem, resulting in log n depth.
π§ Code (C)
π§βπ» Code (C++)
β‘ View Alternative Approaches with Code and Analysis
π 2οΈβ£ Iterative Pattern Recognition
π‘ Algorithm Steps:
Use iterative approach to avoid recursion stack overhead.
For each bit position i, calculate how many times it appears as set bit in range [1, n].
Pattern: In every (2^(i+1)) numbers, bit i is set exactly 2^i times.
Accumulate contributions from all bit positions.
π Complexity Analysis:
Time: β±οΈ O(log n) - Iterate through all bit positions once
Auxiliary Space: πΎ O(1) - Constant space, no recursion
β
Why This Approach?
No recursion overhead or stack space
More cache-friendly with iterative processing
Direct pattern-based calculation
π 3οΈβ£ Mathematical Formula Approach
π‘ Algorithm Steps:
Increment n by 1 to simplify calculations (count from 0 to n).
For each bit position, calculate complete cycles and remaining elements.
Each cycle of length 2^(i+1) contributes 2^i set bits at position i.
Add remaining contribution if elements exceed complete cycles.
π Complexity Analysis:
Time: β±οΈ O(log n) - Process each bit position once
Auxiliary Space: πΎ O(1) - Only variables needed
β
Why This Approach?
Clean mathematical formula
No recursion or complex branching
Efficient bit manipulation
π 4οΈβ£ DP Memoization Approach
π‘ Algorithm Steps:
Use memoization to cache previously computed results.
Apply same recursive logic but store intermediate results.
Before computing, check if result exists in cache.
Significantly faster for multiple queries or repeated subproblems.
π Complexity Analysis:
Time: β±οΈ O(log n) - Each unique subproblem solved once
Auxiliary Space: πΎ O(log n) - Memoization map storage
β
Why This Approach?
Optimal for multiple queries on overlapping ranges
Avoids redundant calculations
Good balance between time and space
π π Comparison of Approaches
π Approach
β±οΈ Time Complexity
πΎ Space Complexity
β Pros
β οΈ Cons
π― Recursive Pattern
π’ O(log n)
π‘ O(log n)
π Clean mathematical formula
π§ Recursion stack overhead
π Iterative Pattern
π’ O(log n)
π’ O(1)
β‘ No recursion overhead
π§ Slightly complex logic
π Mathematical Formula
π’ O(log n)
π’ O(1)
π Optimal bit manipulation
π§ Requires pattern understanding
π DP Memoization
π’ O(log n)
π‘ O(log n)
π― Good for multiple queries
πΎ Extra space for memoization
π Best Choice Recommendation
π― Scenario
ποΈ Recommended Approach
π₯ Performance Rating
π Optimal performance needed
π₯ Iterative Pattern
β β β β β
π Code clarity
π₯ Recursive Pattern
β β β β β
π§ Multiple queries
π₯ DP Memoization
β β β β β
π― Interview/Competitive
π Mathematical Formula
β β β β β
β Code (Java)
π Code (Python)
π§ Contribution and Support
For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: π¬ Any Questions?. Let's make this learning journey more collaborative!
β If you find this helpful, please give this repository a star! β
πVisitor Count
Last updated