Facebook Pixel

190. Reverse Bits

Problem Description

You are given a 32-bit signed integer n. Your task is to reverse all the bits in this integer and return the resulting value.

When reversing bits, the bit at position 0 (rightmost/least significant bit) should move to position 31 (leftmost/most significant bit), the bit at position 1 should move to position 30, and so on. Each bit maintains its value (0 or 1) but changes its position to create a mirror image of the original bit pattern.

For example, if you have the binary representation 00000010100101000001111010011100, after reversing the bits, you would get 00111001011110000010100101000000.

The solution works by iterating through all 32 bits of the input number. For each iteration i:

  • Extract the least significant bit of n using (n & 1)
  • Place this bit at position (31 - i) in the result using left shift: (n & 1) << (31 - i)
  • Combine it with the result using the OR operation: ans |= (n & 1) << (31 - i)
  • Right shift n by 1 to process the next bit: n >>= 1

This process continues for all 32 bits, effectively reversing the entire bit sequence of the input integer.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

To reverse the bits of a number, we need to swap the positions of bits symmetrically around the center. The bit at position 0 should go to position 31, the bit at position 1 should go to position 30, and so on.

Think of it like reversing a string - you would take characters from one end and place them at the opposite end. Similarly, with bits, we need to take each bit from its current position and place it at its mirror position.

The key insight is that we can process the bits one by one from right to left (least significant to most significant). As we examine each bit:

  1. We need to extract it from its current position
  2. We need to place it at its new reversed position

To extract the rightmost bit, we use n & 1, which gives us the value (0 or 1) of the least significant bit.

To place this bit at its reversed position, we need to shift it left. If we're processing the i-th bit (counting from 0), its reversed position would be 31 - i. So we shift the extracted bit left by 31 - i positions using << (31 - i).

After processing each bit, we shift n right by 1 position (n >>= 1) to bring the next bit into the least significant position for processing in the next iteration.

By accumulating all these repositioned bits using the OR operation (|=), we build up the reversed number bit by bit. After 32 iterations, we've processed all bits and have our complete reversed result.

This approach is efficient because it processes each bit exactly once and uses simple bitwise operations that are very fast at the hardware level.

Solution Approach

The solution uses bit manipulation to reverse the bits of a 32-bit integer. Let's walk through the implementation step by step:

Algorithm Overview: We iterate through all 32 bits of the input number, extracting each bit from the right side and placing it at the corresponding position on the left side of our result.

Step-by-step Implementation:

  1. Initialize the result variable: Start with ans = 0, which will store our reversed bit pattern.

  2. Loop through 32 bits: Use a for loop with i ranging from 0 to 31 to process each bit position.

  3. Extract and reposition each bit: For each iteration i:

    • Extract the rightmost bit of n using n & 1. This AND operation with 1 gives us the value of the least significant bit (either 0 or 1).
    • Calculate the reversed position as 31 - i. When i = 0, the bit goes to position 31; when i = 31, the bit goes to position 0.
    • Shift the extracted bit to its new position using (n & 1) << (31 - i).
    • Combine this bit with our result using the OR operation: ans |= (n & 1) << (31 - i).
  4. Prepare for next bit: After processing the current bit, right shift n by 1 position (n >>= 1) to bring the next bit into the least significant position for the next iteration.

Example Walkthrough: Let's say n = 5 (binary: 00000000000000000000000000000101)

  • Iteration 0: Extract bit 1, place at position 31 β†’ ans = 10000000000000000000000000000000
  • Iteration 1: Extract bit 0, place at position 30 β†’ ans = 10000000000000000000000000000000
  • Iteration 2: Extract bit 1, place at position 29 β†’ ans = 10100000000000000000000000000000
  • Continue for remaining 29 iterations...

After all 32 iterations, we return ans which contains the reversed bit pattern.

Time Complexity: O(1) - We always iterate exactly 32 times regardless of input. Space Complexity: O(1) - We only use a constant amount of extra space.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a small example with n = 11 (in decimal).

Initial Setup:

  • Input: n = 11
  • Binary: 00000000000000000000000000001011
  • Result: ans = 0

Key Iterations:

Iteration 0 (i=0):

  • Current n: ...001011
  • Extract rightmost bit: n & 1 = 1
  • Place at position 31: 1 << 31
  • Update result: ans = 10000000000000000000000000000000
  • Shift n right: n = ...000101

Iteration 1 (i=1):

  • Current n: ...000101
  • Extract rightmost bit: n & 1 = 1
  • Place at position 30: 1 << 30
  • Update result: ans = 11000000000000000000000000000000
  • Shift n right: n = ...000010

Iteration 2 (i=2):

  • Current n: ...000010
  • Extract rightmost bit: n & 1 = 0
  • Place at position 29: 0 << 29
  • Result unchanged: ans = 11000000000000000000000000000000
  • Shift n right: n = ...000001

Iteration 3 (i=3):

  • Current n: ...000001
  • Extract rightmost bit: n & 1 = 1
  • Place at position 28: 1 << 28
  • Update result: ans = 11010000000000000000000000000000
  • Shift n right: n = ...000000

Iterations 4-31:

  • Since n = 0 after iteration 3, all remaining bits are 0
  • n & 1 = 0 for all remaining iterations
  • The result remains: ans = 11010000000000000000000000000000

Final Result:

  • Binary: 11010000000000000000000000000000
  • Decimal: 3489660928

The original bits 1011 from the rightmost positions have been moved to the leftmost positions as 1101, effectively reversing the bit pattern across the entire 32-bit integer.

Solution Implementation

1class Solution:
2    def reverseBits(self, n: int) -> int:
3        """
4        Reverse the bits of a 32-bit unsigned integer.
5      
6        Args:
7            n: A 32-bit unsigned integer to reverse
8          
9        Returns:
10            The integer with bits reversed
11        """
12        result = 0
13      
14        # Process all 32 bits
15        for i in range(32):
16            # Extract the least significant bit from n using AND operation
17            # Shift it to its reversed position (31-i) and add to result using OR
18            result |= (n & 1) << (31 - i)
19          
20            # Right shift n by 1 to process the next bit in the next iteration
21            n >>= 1
22          
23        return result
24
1public class Solution {
2    /**
3     * Reverses the bits of a 32-bit unsigned integer.
4     * For example: 00000010100101000001111010011100 becomes 00111001011110000010100101000000
5     * 
6     * @param n - the input integer to reverse (treated as unsigned)
7     * @return the integer with reversed bits
8     */
9    public int reverseBits(int n) {
10        int result = 0;
11      
12        // Process all 32 bits
13        for (int bitPosition = 0; bitPosition < 32 && n != 0; bitPosition++) {
14            // Extract the least significant bit (rightmost) from n
15            int currentBit = n & 1;
16          
17            // Place the extracted bit at the mirrored position from the left
18            // (31 - bitPosition) calculates the reverse position
19            result |= currentBit << (31 - bitPosition);
20          
21            // Right shift n by 1 position (unsigned shift to handle negative numbers correctly)
22            n >>>= 1;
23        }
24      
25        return result;
26    }
27}
28
1class Solution {
2public:
3    uint32_t reverseBits(uint32_t n) {
4        uint32_t result = 0;
5      
6        // Process each bit position (up to 32 bits)
7        // Early termination when n becomes 0 (optimization)
8        for (int i = 0; i < 32 && n != 0; ++i) {
9            // Extract the least significant bit (LSB) of n
10            // Place it at position (31 - i) in the result
11            result |= (n & 1) << (31 - i);
12          
13            // Shift n right by 1 to process the next bit
14            n >>= 1;
15        }
16      
17        return result;
18    }
19};
20
1/**
2 * Reverses the bits of a 32-bit unsigned integer
3 * @param n - A positive integer to reverse bits for
4 * @returns The integer with bits reversed
5 */
6function reverseBits(n: number): number {
7    let result: number = 0;
8  
9    // Process each of the 32 bits
10    for (let i = 0; i < 32 && n > 0; i++) {
11        // Extract the rightmost bit of n using bitwise AND with 1
12        // Then shift it to its reversed position (31 - i) and OR it with result
13        result |= (n & 1) << (31 - i);
14      
15        // Right shift n by 1 to process the next bit
16        n >>= 1;
17    }
18  
19    // Use unsigned right shift to ensure the result is treated as unsigned 32-bit integer
20    return result >>> 0;
21}
22

Time and Space Complexity

The time complexity is O(1), not O(log n) as stated in the reference answer. This is because the loop always runs exactly 32 iterations regardless of the input value n. Even though we're processing a 32-bit integer, the number of operations is constant and doesn't scale with the magnitude of n.

The space complexity is O(1), which matches the reference answer. The algorithm only uses a fixed amount of extra space for the variable ans and the loop counter i, regardless of the input size.

The reference answer appears to be incorrect regarding time complexity. For this specific problem of reversing bits in a 32-bit integer, the time complexity should be O(1) since we always perform exactly 32 iterations. If this were a more general bit reversal problem where the number of bits varied with n, then O(log n) would be appropriate since the number of bits in n is proportional to log n.

Common Pitfalls

1. Early Termination When n Becomes 0

A common mistake is to optimize by breaking the loop early when n becomes 0, thinking all remaining bits are 0:

# INCORRECT approach
def reverseBits(self, n: int) -> int:
    result = 0
    for i in range(32):
        if n == 0:  # Wrong! This causes incorrect results
            break
        result |= (n & 1) << (31 - i)
        n >>= 1
    return result

Why this fails: Even if n becomes 0 during iteration, we still need to continue placing zeros in the remaining positions. Breaking early leaves those positions unprocessed, resulting in incorrect bit placement.

Example: For n = 1 (binary: 00000000000000000000000000000001), the correct reversal is 10000000000000000000000000000000 (2147483648). But breaking early after the first iteration would incorrectly return 2147483648 without properly handling the remaining bit positions.

2. Using Wrong Shift Direction or Amount

Another pitfall is confusing the shift operations:

# INCORRECT approaches
result |= (n & 1) << i  # Wrong: shifts to wrong position
result |= (n & 1) >> (31 - i)  # Wrong: uses right shift instead of left
result |= (n >> 1) << (31 - i)  # Wrong: extracts wrong bit

Solution: Always remember:

  • Use n & 1 to extract the rightmost bit
  • Use << (31 - i) to place it at the reversed position
  • Use n >>= 1 to move to the next bit

3. Incorrect Bit Position Calculation

Some might incorrectly calculate the reversed position:

# INCORRECT
result |= (n & 1) << (32 - i)  # Wrong: shifts by 32 to 1 instead of 31 to 0
result |= (n & 1) << (30 - i)  # Wrong: incorrect range

Solution: The correct formula is 31 - i because:

  • Bit positions range from 0 to 31 (total 32 positions)
  • When i = 0, we want position 31
  • When i = 31, we want position 0

4. Not Processing All 32 Bits

Processing fewer than 32 bits leads to incomplete reversal:

# INCORRECT
for i in range(16):  # Wrong: only processes half the bits
    result |= (n & 1) << (31 - i)
    n >>= 1

Solution: Always iterate exactly 32 times to ensure all bits are properly reversed, regardless of the input value.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

What's the output of running the following function using input [30, 20, 10, 100, 33, 12]?

1def fun(arr: List[int]) -> List[int]:
2    import heapq
3    heapq.heapify(arr)
4    res = []
5    for i in range(3):
6        res.append(heapq.heappop(arr))
7    return res
8
1public static int[] fun(int[] arr) {
2    int[] res = new int[3];
3    PriorityQueue<Integer> heap = new PriorityQueue<>();
4    for (int i = 0; i < arr.length; i++) {
5        heap.add(arr[i]);
6    }
7    for (int i = 0; i < 3; i++) {
8        res[i] = heap.poll();
9    }
10    return res;
11}
12
1class HeapItem {
2    constructor(item, priority = item) {
3        this.item = item;
4        this.priority = priority;
5    }
6}
7
8class MinHeap {
9    constructor() {
10        this.heap = [];
11    }
12
13    push(node) {
14        // insert the new node at the end of the heap array
15        this.heap.push(node);
16        // find the correct position for the new node
17        this.bubble_up();
18    }
19
20    bubble_up() {
21        let index = this.heap.length - 1;
22
23        while (index > 0) {
24            const element = this.heap[index];
25            const parentIndex = Math.floor((index - 1) / 2);
26            const parent = this.heap[parentIndex];
27
28            if (parent.priority <= element.priority) break;
29            // if the parent is bigger than the child then swap the parent and child
30            this.heap[index] = parent;
31            this.heap[parentIndex] = element;
32            index = parentIndex;
33        }
34    }
35
36    pop() {
37        const min = this.heap[0];
38        this.heap[0] = this.heap[this.size() - 1];
39        this.heap.pop();
40        this.bubble_down();
41        return min;
42    }
43
44    bubble_down() {
45        let index = 0;
46        let min = index;
47        const n = this.heap.length;
48
49        while (index < n) {
50            const left = 2 * index + 1;
51            const right = left + 1;
52
53            if (left < n && this.heap[left].priority < this.heap[min].priority) {
54                min = left;
55            }
56            if (right < n && this.heap[right].priority < this.heap[min].priority) {
57                min = right;
58            }
59            if (min === index) break;
60            [this.heap[min], this.heap[index]] = [this.heap[index], this.heap[min]];
61            index = min;
62        }
63    }
64
65    peek() {
66        return this.heap[0];
67    }
68
69    size() {
70        return this.heap.length;
71    }
72}
73
74function fun(arr) {
75    const heap = new MinHeap();
76    for (const x of arr) {
77        heap.push(new HeapItem(x));
78    }
79    const res = [];
80    for (let i = 0; i < 3; i++) {
81        res.push(heap.pop().item);
82    }
83    return res;
84}
85

Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More