githubEdit

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 Linkarrow-up-right

🧩 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

  1. 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

  2. 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

  3. 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)

  4. Base Case:

    • If n == 0, return 0

    • This ensures termination of recursion

  5. 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++)

chevron-right⚑ View Alternative Approaches with Code and Analysishashtag

πŸ“Š 2️⃣ Iterative Pattern Recognition

πŸ’‘ Algorithm Steps:

  1. Use iterative approach to avoid recursion stack overhead.

  2. For each bit position i, calculate how many times it appears as set bit in range [1, n].

  3. Pattern: In every (2^(i+1)) numbers, bit i is set exactly 2^i times.

  4. 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:

  1. Increment n by 1 to simplify calculations (count from 0 to n).

  2. For each bit position, calculate complete cycles and remaining elements.

  3. Each cycle of length 2^(i+1) contributes 2^i set bits at position i.

  4. 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:

  1. Use memoization to cache previously computed results.

  2. Apply same recursive logic but store intermediate results.

  3. Before computing, check if result exists in cache.

  4. 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?arrow-up-right. Let's make this learning journey more collaborative!

⭐ If you find this helpful, please give this repository a star! ⭐


πŸ“Visitor Count

Visitor counter

Last updated