Bit Manipulation: XOR Tricks and Bitmasking

Sanjeev SharmaSanjeev Sharma
3 min read

Advertisement

Bit Manipulation

Core Operations

AND  (&): 1 only if both bits are 1
OR   (|): 1 if either bit is 1
XOR  (^): 1 if bits differ
NOT  (~): flip all bits
SHL  (<<): multiply by 2^k
SHR  (>>): divide by 2^k (floor)

Python Tricks

# Get k-th bit (0-indexed from right)
def get_bit(n, k): return (n >> k) & 1

# Set k-th bit
def set_bit(n, k): return n | (1 << k)

# Clear k-th bit
def clear_bit(n, k): return n & ~(1 << k)

# Toggle k-th bit
def toggle_bit(n, k): return n ^ (1 << k)

# Check if power of 2
def is_pow2(n): return n > 0 and (n & (n-1)) == 0

# Count set bits (Brian Kernighan)
def popcount(n):
    count = 0
    while n:
        n &= n - 1  # remove lowest set bit
        count += 1
    return count

# Lowest set bit
def lsb(n): return n & (-n)

# Remove lowest set bit
def remove_lsb(n): return n & (n-1)

# XOR tricks
# a ^ a = 0
# a ^ 0 = a
# XOR is commutative and associative

# Find single element in array where all others appear twice
def single_number(nums):
    result = 0
    for n in nums:
        result ^= n
    return result

# Find two singles where all others appear twice
def two_singles(nums):
    xor = 0
    for n in nums: xor ^= n
    # xor = a ^ b; find any set bit
    diff_bit = xor & (-xor)
    a = 0
    for n in nums:
        if n & diff_bit:
            a ^= n
    return a, xor ^ a

C++ Implementation

#include <bits/stdc++.h>
using namespace std;

// Count set bits efficiently
int popcount(int n) { return __builtin_popcount(n); }
int popcount64(long long n) { return __builtin_popcountll(n); }

// Iterate all subsets of mask
void enumSubsets(int mask) {
    for (int sub = mask; sub > 0; sub = (sub - 1) & mask) {
        // process sub
    }
}

// Iterate all subsets of size k of n elements
void enumKSubsets(int n, int k) {
    int sub = (1 << k) - 1;
    while (sub < (1 << n)) {
        // process sub
        int c = sub & (-sub);
        int r = sub + c;
        sub = (((r ^ sub) >> 2) / c) | r;  // Gosper's hack
    }
}

// XOR swap (no temp variable)
void xor_swap(int& a, int& b) { a ^= b; b ^= a; a ^= b; }

Bitmask DP Example: Traveling Salesman

def tsp(dist):
    n = len(dist)
    INF = float('inf')
    dp = [[INF] * n for _ in range(1 << n)]
    dp[1][0] = 0  # start at node 0, visited = {0}

    for mask in range(1 << n):
        for u in range(n):
            if not (mask >> u & 1): continue
            if dp[mask][u] == INF: continue
            for v in range(n):
                if mask >> v & 1: continue
                new_mask = mask | (1 << v)
                dp[new_mask][v] = min(dp[new_mask][v], dp[mask][u] + dist[u][v])

    full = (1 << n) - 1
    return min(dp[full][u] + dist[u][0] for u in range(n))

LeetCode Problems

  • 136. Single Number — XOR
  • 191. Number of 1 Bits — popcount
  • 338. Counting Bits — DP: bits[i] = bits[i>>1] + (i&1)
  • 371. Sum of Two Integers — bit addition without +
  • 477. Total Hamming Distance — bit column counting
  • 847. Shortest Path Visiting All Nodes — bitmask BFS

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro