1. Overview

  • Bit manipulation uses binary operations (AND, OR, XOR, NOT) directly on bits to perform tasks

  • Advantages:

    • Efficiency: Faster than conventionally arithmetic operations
    • Low Memory Usage: Directly working with bits requires fewer resources
  • Applications:

    • Power of Two Checks: Quick check if a number is a power of two
    • Swapping Bits: Efficient swapping of values without temporary storage
    • Setting/Clearing/Flipping Bits: Manipulating individual bits for control flags
    • Optimizations: Can be used in low-level optimizations and certain cryptographic algorithms

2. Bitwise Operations

OperationSymbolDescriptionExample
AND&Sets each bit to 1 if both bits are 1a & b
OR|Sets each bit to 1 if at least one bit is 1a | b
XOR^Sets each bit to 1 if only one bit is 1a ^ b
NOT~Inverts all bits~a
Left Shift<<Shifts bits left, filling with 0 on the righta << 1 (multiplies by 2)
Right Shift>>Shifts bits right, discarding right-most bitsa >> 1 (divides by 2)

3. Key Bit Manipulation Techniques

Checking if a Number is Odd or Even

if the least significant bit(rightmost bit) is 1, then the number is odd, otherwise, its even

bool isOdd(int n) {
    return (n & 1) == 1;
}

Checking if a Number is a Power of Two

for numbers that are powers of two, only a single bit is set (e.g., 2=10, 4=100) subtracting 1 flips all lower bits, so n & (n - 1) results in 0

bool isPowerOfTwo(int n) {
    return (n > 0) && ((n & (n - 1)) == 0);
}

Counting the Number of Set Bits (Hamming Weight)

The operation checks each bit and counts those that are 1

int countSetBits(int n) {
    int count = 0;
    while (n > 0) {
        count += (n & 1);
        n >>= 1;
    }
    return count;
}

Swapping Two Numbers Without a Temporary Variable

XOR operations cancel out when applied in this specific sequence, allowing swapping without extra storage

void swap(int &a, int &b) {
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
}

Setting, Clearing and Toggling Specific Bits

Setting the k-th Bit (turn on a specific bit):

int setBit(int n, int k) {
    return n | (1 << k);
}

Clearing the k-th Bit (turn off a specific bit):

int clearBit(int n, int k) {
    return n & ~(1 << k);
}

Toggling the k-th Bit (flip a specific bit):

int toggleBit(int n, int k) {
    return n ^ (1 << k);
}

Advanced Applications

Finding the Single Non-Repeating Element

In an array where every element appears twice except one, find the unique element Explanation: XORing all elements results in the unique element, as duplicate elements cancel each other out

int singleNonRepeating(vector<int>& nums) {
    int result = 0;
    for(int num : nums) {
        result ^= nums;
    }
    return result;
}

Finding the Missing Number

In an array containing numbers from 0 to n with one missing, find the missing number Explanation: XORing all indices and elements results in the missing number, as all pair elements cancel out

int missingNumber(vector<int>& nums) {
    int n = nums.size();
    int result = n;
    for(int i=0; i < n; i++) {
        result ^= i ^ nums[i];
    }
    return result;
}