Reverse Bits
franklinqin0 BitD&C
# Solution
There are a myriad of solutions for this problem. Complexity is too obvious to note down.
# 1-liner Cheating
Can use the built-in int
, bin
, zfill
, and string reverse [::-1]
to achieve a 1-liner solution.
def reverseBits(self, n):
return int(bin(n)[2:].zfill(32)[::-1], 2)
1
2
2
# Bit Mask
Mask bits from right to left.
def reverseBits(self, n: int) -> int:
res = 0
mask = 1
for _ in range(32):
res <<= 1
if mask&n:
res |= 1
mask <<= 1
return res
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Mask bits from left to right.
def reverseBits(self, n: int) -> int:
res = 0
mask = 1<<31
for _ in range(32):
if n&1:
res |= mask
mask >>= 1
n >>= 1
return res
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# Bit Shift
Shift bit by bit in a for loop.
def reverseBits(self, n: int) -> int:
res = 0
for _ in range(32):
res = (res<<1) + (n&1)
n>>=1
return res
1
2
3
4
5
6
2
3
4
5
6
Shift bit by bit in a while loop w/ power
.
def reverseBits(self, n):
res, power = 0, 31
while n:
res += (n & 1) << power
n = n >> 1
power -= 1
return res
1
2
3
4
5
6
7
2
3
4
5
6
7
# Shift out Rightmost 1
Every time only shift out rightmost 1. This saves time when n
has many 0 bits.
def reverseBits(self, n: int) -> int:
res = (n%2)<<31
power = 31
while power>0:
tmp = n&-n
shift = int(math.log(tmp, 2)) if tmp>1 else 1
power -= shift
n >>= shift
res += (n&1)<<power
return res
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# Follow Up
If this function is called many times, how would you optimize it?
# Pseudocode
We should come up with a lookup table to store mappings. The following code derives from EPI in Python, page 28, which reverses bits for a 64-bit integer.
def reverseBits(x):
MASK_SIZE = 16
BIT_MASK = 0xFFFF
return (PRECOMPUTED_REVERSE[x & BIT_MASK] << (3 * MASK_SIZE)
| PRECOMPUTED_REVERSE[(x >> MASK_SIZE) & BIT_MASK] << (2 * MASK_SIZE)
| PRECOMPUTED_REVERSE[(x >> (2 * MASK_SIZE) & BIT_MASK] << MASK_SIZE
| PRECOMPUTED_REVERSE[(x >> (3 * MASK_SIZE) & BIT_MASK])
1
2
3
4
5
6
7
2
3
4
5
6
7
# Divide & Conquer
At each of following steps, intermediate result is merged and input to next step:
- break the 32-bit integer into 2 blocks of 16-bits and swap
- break the 16-bit integer into 2 blocks of 8-bits and swap
- break the 8-bit integer into 2 blocks of 4-bits and swap
- break the 4-bit integer into 2 blocks of 2-bits and swap
- break the 2-bit integer into 2 blocks of 1-bit and swap
def reverseBits(self, n):
n = (n >> 16) | (n << 16)
n = ((n & 0xff00ff00) >> 8) | ((n & 0x00ff00ff) << 8)
n = ((n & 0xf0f0f0f0) >> 4) | ((n & 0x0f0f0f0f) << 4)
n = ((n & 0xcccccccc) >> 2) | ((n & 0x33333333) << 2)
n = ((n & 0xaaaaaaaa) >> 1) | ((n & 0x55555555) << 1)
return n
1
2
3
4
5
6
7
2
3
4
5
6
7