LeetCode: Bit Manipulation

Bit Manipulation Intro
What is Bit Manipulation
bits!
Bit Manipulation IRL
bits!
Bit Manipulation Application: Bit Manipulation
Pattern: bits!
Ex: bits numbers!!
def bitss!(n: int) -> int:
return n+1
136. Single Number ::1:: - Easy
Topics: Array, Bit Manipulation
Intro
Given a non-empty array of integers nums, every element appears twice except for one. Find that single one. You must implement a solution with a linear runtime complexity and use only constant extra space.
Example Input | Output |
---|---|
nums = [2,2,1] | 1 |
nums = [4,1,2,1,2] | 4 |
nums = [1] | 1 |
Constraints:
1 ≤ nums.length ≤ 3 * 104
-3 * 104 ≤ nums[i] ≤ 3 * 104
Each element in the array appears twice except for one element which appears only once.
Abstraction
Given a list of integers, find the integer that only appears once.
Space & Time Complexity
Solution | Time Complexity | Space Complexity | Time Remark | Space Remark |
---|---|---|---|---|
Bug | Error |
---|---|
Brute Force:
Aspect | Time Complexity | Space Complexity | Time Remarks | Space Remarks |
---|---|---|---|---|
Find the Bug:
Solution 1: Bit Manipulation XOR Trick - Bit Manipulation/Bit Manipulation
def singleNumber(self, nums: List[int]) -> int:
# Note:
# 1. num XOR num -> 0
# 2. num XOR 0 -> num
# 3. XOR is commutative and associative
# 4. Iterate XOR over all pairs of numbers to leave the unique number
result = 0
# Accumulative XOR to generate the unique number
for num in nums:
result ^= num
# overall: time complexity O(n)
# overall: space complexity O(1)
return result
191. Number of 1 Bits ::2:: - Easy
Topics: Divide and Conquer, Bit Manipulation
Intro
Given a positive integer n, write a function that returns the number of set bits in its binary representation (also known as the Hamming weight). A set bit refers to a bit in the binary representation of a number that has a value of 1. Follow up: If this function is called many times, how would you optimize it?
Example Input | Output |
---|---|
n = 11 | 3 |
n = 128 | 1 |
n = 2147483645 | 30 |
Constraints:
1 ≤ n ≤ 231 - 1
Abstraction
Given an integer, return how many bits are set to 1 in its binary representation.
Space & Time Complexity
Solution | Time Complexity | Space Complexity | Time Remark | Space Remark |
---|---|---|---|---|
Bug | Error |
---|---|
Brute Force:
Aspect | Time Complexity | Space Complexity | Time Remarks | Space Remarks |
---|---|---|---|---|
Find the Bug:
Solution 1: Basic Shift and Mask - Bit Manipulation/Bit Manipulation
def hammingWeight(self, n: int) -> int:
# Note:
# 1. Given a 32-bit signed integer, check all bits for set
# 2. Set bit check -> check lowest bit
# 3. Iterate -> shift binary representation by 1
# Result -> count of set bits of binary representation
count = 0
for _ in range(32):
# set bit check -> validate if lowest bit is 1
count += n & 1
# iterate -> shift right by 1 regardless
n >>= 1
# overall: time complexity O(32) = O(1)
# overall: space complexity O(1)
return count
Solution 2: Brian Kernighan Algorithm - Bit Manipulation/Bit Manipulation
def hammingWeight(self, n: int) -> int:
# Note:
# 1. Iterate while some bit is set
# 2. Removes the lowest/rightmost set bit
# 3. Add to count
# Result -> count number of set bits
count = 0
# continues while some bit is set
while n:
# clears the right most 1 and everything to the right of it
# n = 101000
# n - 1 = 100111
# ----------------
# n&(n-1)= 100000
n &= (n - 1)
# add to set bit count
count += 1
# overall: time complexity O(k), k = number of set bits
# overall: space complexity O(1)
return count
338. Counting Bits ::2:: - Easy
Topics: Dynamic Programming, Bit Manipulation
Intro
Given an integer n, return an array ans of length n + 1 such that for each i (0 < = i < = n), ans[i] is the number of 1's in the binary representation of i.
Example Input | Output |
---|---|
n = 2 | [0,1,1] |
n = 5 | [0,1,1,2,1,2] |
Constraints:
0 ≤ n ≤ 105
Abstraction
Given an integer, return an array representing 0 -> n, where each index is the number of set bits for that integer.
Space & Time Complexity
Solution | Time Complexity | Space Complexity | Time Remark | Space Remark |
---|---|---|---|---|
Bug | Error |
---|---|
Brute Force:
Aspect | Time Complexity | Space Complexity | Time Remarks | Space Remarks |
---|---|---|---|---|
Find the Bug:
Solution 1: DP with Integer Division + Bit Shift - Bit Manipulation/Bit Manipulation
def countBits(self, n: int) -> List[int]:
# Note:
# 1. DP relation via bit manipulation
# i >> 1 removes the least significant bit
# i & 1 checks if least significant bit is set
# 2. Recurrence:
# dp[i] = dp[i >> 1] + (i & 1)
# 3. Build array bottom-up from 0 to n
ans = [0] * (n + 1)
for i in range(1, n + 1):
ans[i] = ans[i >> 1] + (i & 1)
# overall: time complexity O(n)
# overall: space complexity O(n)
return ans
190. Reverse Bits ::1:: - Easy
Topics: Divide and Conquer, Bit Manipulation
Intro
Reverse bits of a given 32 bits signed integer. Follow up: If this function is called many times, how would you optimize it?
Example Input | Output |
---|---|
n = 43261596 | 964176192 |
n = 2147483644 | 1073741822 |
Constraints:
0 ≤ n ≤ 231 - 2
n is even
Abstraction
Reverse bits of a 32 signed integer.
Space & Time Complexity
Solution | Time Complexity | Space Complexity | Time Remark | Space Remark |
---|---|---|---|---|
Bug | Error |
---|---|
Brute Force:
Aspect | Time Complexity | Space Complexity | Time Remarks | Space Remarks |
---|---|---|---|---|
Find the Bug:
Solution 1: Iterative Bit Manipulation - Bit Manipulation/Bit Manipulation
def reverseBits(self, n: int) -> int:
# Note:
# 1. Given a 32-bit signed integer
# 2. Iterate res left by 1 and n right by 1 to continuing copying right most bit
# Result -> reversed n
result = 0
# Iterate over 32 bits
for _ in range(32):
# shift result left by 1, making space for new rightmost bit
result <<= 1
# copy n's rightmost bit (least significant) to res
result |= n & 1
# shift n right by 1, preparing next bit for copy
n >>= 1
# overall: time complexity O(n)
# overall: space complexity O(n)
return result
268. Missing Number ::2:: - Easy
Topics: Array, Hash Table, Math, Binary Search, Bit Manipulation, Sorting
Intro
Given an array nums containing n distinct numbers in the range [0, n], return the only number in the range that is missing from the array. Follow up: Could you implement a solution using only O(1) extra space complexity and O(n) runtime complexity?
Example Input | Output |
---|---|
nums = [3,0,1] | 2 |
nums = [0,1] | 2 |
nums = [9,6,4,2,3,5,7,0,1] | 8 |
Constraints:
n == nums.length
1 ≤ n ≤ 104
0 ≤ nums[i] ≤ n
All the numbers of nums are unique.
Abstraction
Given an array of n distinct numbers, in range [0, n], return the only number that is missing from the range.
Space & Time Complexity
Solution | Time Complexity | Space Complexity | Time Remark | Space Remark |
---|---|---|---|---|
Bug | Error |
---|---|
Brute Force:
Aspect | Time Complexity | Space Complexity | Time Remarks | Space Remarks |
---|---|---|---|---|
Find the Bug:
Solution 1: Verify Against Math Formula - Bit Manipulation/Bit Manipulation
def missingNumber(self, nums: List[int]) -> int:
# Note:
# Math approach
# 0. The sum of numbers 0 -> n is (n * (n+1)/2)
# 1. Sum all elements in nums
# 2. Missing = expected sum - actual sum
n = len(nums)
expected_sum = n * (n + 1) // 2
sum = 0
for n in nums:
sum += n
missing = expected_sum - sum
# overall: time complexity O(n)
# overall: space complexity O(1)
return missing
Solution 2: XOR Trick - Bit Manipulation/Bit Manipulation
def missingNumber(self, nums: List[int]) -> int:
# Note:
# XOR approach
# 1. num XOR num -> 0, all paired numbers cancel out
# 2. Iterate over range -> num XOR index -> 0
# 3. Missing number -> will not XOR correctly, will remain at end
# Result -> missing number
n = len(nums)
missing = 0
# loop from 0 to n inclusive
for i in range(n + 1):
# XOR index and array value
if i < n:
missing ^= i ^ nums[i]
# i == n, just XOR the number n, avoid out of bounds index
else:
missing ^= i
# Time Complexity: O(n)
# Space Complexity: O(1)
return missing
371. Sum of Two Integers ::1:: - Medium
Topics: Math, Bit Manipulation
Intro
Given two integers a and b, return the sum of the two integers without using the operators + and -.
Example Input | Output |
---|---|
a = 1, b = 2 | 3 |
a = 2, b = 3 | 5 |
Constraints:
Abstraction
Given two integers, return the sum without using operators.
Space & Time Complexity
Solution | Time Complexity | Space Complexity | Time Remark | Space Remark |
---|---|---|---|---|
Bug | Error |
---|---|
Brute Force:
Aspect | Time Complexity | Space Complexity | Time Remarks | Space Remarks |
---|---|---|---|---|
Find the Bug:
Solution 1: Bit Manipulation - Bit Manipulation/Bit Manipulation
def getSum(self, a: int, b: int) -> int:
# -----------------------------------------
# a b '^' sum (without carry) carry
# 0 0 0 0
# 0 1 1 0
# 1 0 1 0
# 1 1 0 1
# -----------------------------------------
# Note:
# all bits are processed in parallel, one bit at a time
# Iteration 1: sum bits 0 and 1 (rightmost two bits)
# a = 0110
# b = 0011
# sum_ = a ^ b = 0101
# carry = (a & b) << 1 = 0100 (carry from bit 1 moves to bit 2)
# Iteration 2: sum bits 2 and 2 (carry affecting bit 2)
# a = sum_ = 0101
# b = carry = 0100
# sum_ = a ^ b = 0001
# carry = (a & b) << 1 = 0100 << 1 = 1000 (carry from bit 2 moves to bit 3)
# Iteration 3: sum bits 3 and 3 (carry affecting highest bit)
# a = 0001
# b = 1000
# sum_ = 1001
# carry = (a & b) << 1 = 0000 (no more carry)
# Done, carry is 0 → final sum = 1001 (9)
# -----------------------------------------
# Note:
# 1. (a ^ b) -> acts as sum without carry, mask ensures all operations are restricted to 32 bits
# 2. (a & b) << 1 -> Carry is 1 only when both bits are 1, otherwise 0
# 2. carry -> Use AND (&) + left shift (<<)
# 3. Repeat until carry is 0 -> no value left
# 4. Handle negative numbers with 32-bit mask
# Result ->
# limit to 32 bits
MASK = 0xFFFFFFFF
maxInt = 2**31 - 1
# while carry is not 0
while b != 0:
# sum without carry
sum_ = (a ^ b) & MASK
# carry
carry = ((a & b) << 1) & MASK
# update a and b
a, b = sum_, carry
# if a > 2^31-1, it's negative in 32-bit signed
res = a if a <= maxInt else ~(a ^ MASK)
# overall: time complexity O(1)
# overall: space complexity O(1)
return res
7. Reverse Integer ::1:: - Medium
Topics: Math
Intro
Given a signed 32-bit integer x, return x with its digits reversed. If reversing x causes the value to go outside the signed 32-bit integer range [-2^31, 2^31 - 1], then return 0. Assume the environment does not allow you to store 64-bit integers (signed or unsigned).
Example Input | Output |
---|---|
x = 123 | 321 |
x = -123 | -321 |
x = 120 | 21 |
Constraints:
-231 ≤ x ≤ 231 - 1
Abstraction
Given a 32-bit integer, reverse it.
Space & Time Complexity
Solution | Time Complexity | Space Complexity | Time Remark | Space Remark |
---|---|---|---|---|
Bug | Error |
---|---|
Brute Force:
Aspect | Time Complexity | Space Complexity | Time Remarks | Space Remarks |
---|---|---|---|---|
Find the Bug:
Solution 1: Iterative Math Approach - Bit Manipulation/Bit Manipulation
def reverse(self, x: int) -> int:
# -----------------------------------------
# Iterative process: process each digit from right to left
# Example: x = 123
# Iteration 1:
# digit = 123 % 10 = 3
# x = 123 // 10 = 12
# res = 0 * 10 + 3 = 3
#
# Iteration 2:
# digit = 12 % 10 = 2
# x = 12 // 10 = 1
# res = 3 * 10 + 2 = 32
#
# Iteration 3:
# digit = 1 % 10 = 1
# x = 1 // 10 = 0
# res = 32 * 10 + 1 = 321
#
# Done, x == 0 → final reversed number = 321
# -----------------------------------------
# Note:
# 1. Extract digits one by one using modulo 10
# 2. Append to result using multiply by 10 + digit
# 3. Handle negative numbers
# 4. Check for 32-bit overflow
# Result ->
INT_MAX = 2**31 - 1 # 2147483647
INT_MIN = -2**31 # -2147483648
res = 0
sign = 1 if x >= 0 else -1
x = abs(x)
while x != 0:
digit = x % 10
x //= 10
# Check overflow before multiplying by 10
if res > (INT_MAX - digit) // 10:
# would overflow 32-bit signed integer
return 0
res = res * 10 + digit
# Apply original sign
res1 = sign * res
# overall: time complexity O(log10(x))
# overall: space complexity O(1)
return res1