🔢 Bit Manipulation Made Easy

Master the art of bits - the fundamental units of data in computers

🎯 Interactive Learning ⏱️ 30 min read 💻 Live Examples 📚 Complete Guide

🤔 Why Master Bit Manipulation?

⚡ Lightning Fast Operations

Bit operations are the fastest operations a CPU can perform. Multiply by 2? Just shift left!

💾 Memory Optimization

Store 32 boolean flags in a single integer instead of 32 separate variables.

🔐 Cryptography & Security

Essential for encryption algorithms, hash functions, and security protocols.

🎮 Game Development

Collision detection, state machines, and graphics rendering all use bit tricks.

💡 Real-World Example: Unix File Permissions

Ever seen chmod 755? That's bit manipulation!

7 = 111 (read, write, execute), 5 = 101 (read, execute), 5 = 101 (read, execute)

🌟 Bit Manipulation Fundamentals

Understanding Bits - Think of Light Switches! 💡

1
0
1
1
0
1
0
0

Each bit is like a light switch - ON (1) or OFF (0). Together they represent numbers!

Basic Bitwise Operations 🔧
# Basic bitwise operations - your bit toolkit! a = 12 # 1100 in binary b = 10 # 1010 in binary # AND (&) - Both bits must be 1 # Like: "Do you have BOTH permissions?" print(f"{a} & {b} = {a & b}") # 12 & 10 = 8 (1000) # OR (|) - At least one bit must be 1 # Like: "Do you have ANY permission?" print(f"{a} | {b} = {a | b}") # 12 | 10 = 14 (1110) # XOR (^) - Bits must be different # Like: "Toggle the switch!" print(f"{a} ^ {b} = {a ^ b}") # 12 ^ 10 = 6 (0110) # NOT (~) - Flip all bits # Like: "Invert everything!" print(f"~{a} = {~a}") # ~12 = -13 (two's complement) # Left shift (<<) - Multiply by 2^n # Like: "Double it n times!" print(f"{a} << 2 = {a << 2}") # 12 << 2 = 48 (12 * 4) # Right shift (>>) - Divide by 2^n # Like: "Halve it n times!" print(f"{a} >> 2 = {a >> 2}") # 12 >> 2 = 3 (12 / 4)
Essential Bit Manipulation Functions 🛠️
def check_bit(n, i): """Check if ith bit is set (1 or 0)""" return (n & (1 << i)) != 0 def set_bit(n, i): """Set ith bit to 1""" return n | (1 << i) def clear_bit(n, i): """Clear ith bit (set to 0)""" return n & ~(1 << i) def toggle_bit(n, i): """Toggle ith bit (0→1 or 1→0)""" return n ^ (1 << i) def count_set_bits(n): """Count number of 1s (Brian Kernighan's algorithm)""" count = 0 while n: n &= n - 1 # Remove rightmost set bit count += 1 return count # Examples n = 28 # 11100 in binary print(f"Number: {n} (binary: {bin(n)})") print(f"Bit 2 is set: {check_bit(n, 2)}") # True print(f"Set bit 0: {set_bit(n, 0)}") # 29 print(f"Clear bit 3: {clear_bit(n, 3)}") # 20 print(f"Count set bits: {count_set_bits(n)}") # 3

🎮 Interactive Bit Manipulation Demo

Bit Operations Visualizer

Enter two numbers and click "Visualize Operations" to see bit operations in action!

Bit Manipulation Playground

Play with bit operations on any number!

🎩 Clever Bit Tricks

Power of 2 Tricks ⚡
def is_power_of_two(n): """Check if number is power of 2 Powers of 2 have exactly one bit set! Examples: 1(1), 2(10), 4(100), 8(1000) """ return n > 0 and (n & (n - 1)) == 0 def next_power_of_2(n): """Find next power of 2 greater than n""" if n <= 0: return 1 n -= 1 # Handle case where n is already power of 2 n |= n >> 1 n |= n >> 2 n |= n >> 4 n |= n >> 8 n |= n >> 16 return n + 1 # Fast multiplication/division by powers of 2 def multiply_by_power_of_2(n, power): return n << power # n * 2^power def divide_by_power_of_2(n, power): return n >> power # n / 2^power # Examples print(f"Is 16 power of 2? {is_power_of_two(16)}") # True print(f"Is 18 power of 2? {is_power_of_two(18)}") # False print(f"Next power of 2 after 10: {next_power_of_2(10)}") # 16 print(f"5 * 8 = {multiply_by_power_of_2(5, 3)}") # 40
XOR Magic Tricks 🪄
def swap_without_temp(a, b): """Swap two numbers without temporary variable""" a = a ^ b b = a ^ b # b = (a^b)^b = a a = a ^ b # a = (a^b)^a = b return a, b def find_single_number(nums): """Find the single number when all others appear twice XOR properties: a^a=0, a^0=a, XOR is commutative """ result = 0 for num in nums: result ^= num return result def find_missing_number(nums, n): """Find missing number from 0 to n""" xor_all = 0 xor_array = 0 # XOR all numbers from 0 to n for i in range(n + 1): xor_all ^= i # XOR all numbers in array for num in nums: xor_array ^= num # Missing number = xor_all ^ xor_array return xor_all ^ xor_array # Examples print(f"Swap 5 and 7: {swap_without_temp(5, 7)}") # (7, 5) print(f"Single number in [2,2,1]: {find_single_number([2,2,1])}") # 1 print(f"Missing in [0,1,3]: {find_missing_number([0,1,3], 3)}") # 2

🎯 Pro Tip: XOR Properties

  • a ^ a = 0 (anything XOR itself is 0)
  • a ^ 0 = a (anything XOR 0 is itself)
  • XOR is commutative: a ^ b = b ^ a
  • XOR is associative: (a ^ b) ^ c = a ^ (b ^ c)

🚀 Advanced Bit Manipulation

Subset Generation with Bitmasks 🎭
def generate_all_subsets(arr): """Generate all subsets using bit manipulation For n elements, iterate through 0 to 2^n - 1 Each bit represents whether to include element """ n = len(arr) subsets = [] # 2^n possible subsets for mask in range(1 << n): subset = [] for i in range(n): # Check if ith bit is set if mask & (1 << i): subset.append(arr[i]) subsets.append(subset) return subsets # Example: Generate all subsets of [1, 2, 3] arr = [1, 2, 3] subsets = generate_all_subsets(arr) print("All subsets:") for subset in subsets: print(subset) # Output: [], [1], [2], [1,2], [3], [1,3], [2,3], [1,2,3]
Bit Manipulation in Dynamic Programming 🧮
def traveling_salesman_dp(dist): """TSP using DP with bitmask dp[mask][i] = min cost to visit cities in mask, ending at i """ n = len(dist) all_visited = (1 << n) - 1 # dp[mask][last] = minimum cost dp = [[float('inf')] * n for _ in range(1 << n)] # Start from city 0 dp[1][0] = 0 for mask in range(1 << n): for last in range(n): if dp[mask][last] == float('inf'): continue # Try to visit each unvisited city for next_city in range(n): if mask & (1 << next_city): continue # Already visited new_mask = mask | (1 << next_city) dp[new_mask][next_city] = min( dp[new_mask][next_city], dp[mask][last] + dist[last][next_city] ) # Find minimum cost to visit all cities return min(dp[all_visited])

⚠️ Common Pitfalls

  • Operator Precedence: & has lower precedence than ==
  • Signed vs Unsigned: Right shift behaves differently
  • Integer Overflow: Be careful with large shifts
  • Two's Complement: Negative numbers can be tricky

💪 Practice Problems

🟢 Easy: Count Set Bits

Problem: Count the number of 1s in binary representation of a number.

Example: 13 (1101) has 3 set bits

def count_bits(n): """Brian Kernighan's algorithm n & (n-1) removes the rightmost set bit """ count = 0 while n: n &= n - 1 count += 1 return count # Alternative: Built-in method def count_bits_builtin(n): return bin(n).count('1')
🟡 Medium: Single Number II

Problem: Find the single number when all others appear exactly 3 times.

Strategy: Use bit counting - track bits appearing once and twice.

def single_number_ii(nums): """Track bits appearing once and twice""" ones = twos = 0 for num in nums: # Update twos first twos |= ones & num ones ^= num # Reset bits appearing 3 times threes = ones & twos ones &= ~threes twos &= ~threes return ones
🔴 Hard: Maximum XOR in Array

Problem: Find maximum XOR of any two numbers in array.

Strategy: Build prefix and check bit by bit from MSB.

def find_maximum_xor(nums): """Find max XOR using prefix approach""" max_xor = 0 mask = 0 for i in range(31, -1, -1): mask |= (1 << i) prefixes = {num & mask for num in nums} temp = max_xor | (1 << i) for prefix in prefixes: if temp ^ prefix in prefixes: max_xor = temp break return max_xor

🎯 Bit Manipulation Mastery Checklist

  • ✅ Understand all 6 bitwise operators
  • ✅ Know common bit manipulation tricks
  • ✅ Can work with bitmasks for subsets
  • ✅ Understand XOR properties and applications
  • ✅ Can optimize with bit operations