Taro Logo

Reverse Bits

Easy
Apple logo
Apple
2 views
Topics:
Bit Manipulation

Reverse bits of a given 32-bit unsigned integer.

Example:

Given the unsigned integer 43261596 (binary representation 00000010100101000001111010011100), return the integer whose binary representation is the reverse: 964176192 (binary 00111001011110000010100101000000).

Constraints:

  • The input is a 32-bit unsigned integer.

Follow-up:

How would you optimize this if the function is called many times?

Solution


Naive Solution: Bit by Bit Reversal

The most straightforward approach is to iterate through the bits of the input integer and construct the reversed integer bit by bit.

  1. Initialize a variable reversed_n to 0. This will store the reversed integer.
  2. Iterate 32 times (for a 32-bit integer).
  3. In each iteration, shift reversed_n to the left by 1 bit (making space for the new bit).
  4. Extract the least significant bit of n using the bitwise AND operator (n & 1).
  5. Add this bit to reversed_n.
  6. Right-shift n by 1 bit to process the next bit.
  7. Return reversed_n.

Code (Python):

def reverseBits_naive(n: int) -> int:
    reversed_n = 0
    for i in range(32):
        reversed_n <<= 1
        reversed_n |= (n & 1)
        n >>= 1
    return reversed_n

Time Complexity: O(1). We iterate 32 times, which is constant for a 32-bit integer.

Space Complexity: O(1). We use a constant amount of extra space.

Optimal Solution: Using Bit Manipulation and Caching

For optimized solution that uses caching, consider the following approach:

The key idea is to reverse the bits in chunks (e.g., bytes) and then combine the reversed chunks.

  1. Reverse bytes: Create a cache (dictionary or array) to store the reversed values of all possible bytes (0-255). This is precomputed.
  2. Divide and conquer: Divide the 32-bit integer into 4 bytes.
  3. Lookup reversed bytes: For each byte, look up its reversed value from the cache.
  4. Combine reversed bytes: Shift and combine the reversed bytes to construct the final reversed integer.

Code (Python):

class Solution:
    def __init__(self):
        self.cache = {}

    def reverseByte(self, byte):
        if byte not in self.cache:
            reversed_byte = 0
            for i in range(8):
                reversed_byte <<= 1
                reversed_byte |= (byte & 1)
                byte >>= 1
            self.cache[byte] = reversed_byte
        return self.cache[byte]

    def reverseBits(self, n: int) -> int:
        result = 0
        for i in range(4):
            byte = (n >> (i * 8)) & 0xFF  # Extract each byte
            reversed_byte = self.reverseByte(byte)
            result |= (reversed_byte << (8 * (3 - i)))
        return result

Time Complexity: O(1). Although there is a loop, it only iterates four times, making it constant time for a 32-bit integer. Precomputing the reversed byte cache takes O(256) time which is also constant time.

Space Complexity: O(1). The cache stores a maximum of 256 reversed byte values, which is constant space.

Edge Cases

  • Input is 0: The algorithm should correctly handle the case where the input integer is 0. Both the naive and optimized solutions handle this case correctly.
  • Negative Numbers: The problem statement specifies unsigned 32-bit integers. However, if the input is given as a signed integer (as in Java), the algorithm should still work correctly because it operates on the bit representation of the integer.