DSA · Topic 18 of 18 · DP & Advanced Topics

Bit Manipulation

XOR cancels pairs (a ^ a = 0), and x & (x − 1) deletes the lowest 1 bit.

7 problems · O(n) or O(number of bits) time, O(1) space

Step 1 Understand it

Remember it by

XOR cancels pairs (a ^ a = 0), and x & (x − 1) deletes the lowest 1 bit.

Watch it happen

AnimationBits: XOR cancels pairs; shifting reuses smaller answers
Read the animation as text
  1. Every number appears twice except one. XOR (^) compares bits: same bits give 0, different give 1. So x ^ x = 0 and x ^ 0 = x — pairs cancel out.
  2. 000 ^ 100 = 100. Every 1-bit of 4 flips that bit of the running value.
  3. 100 ^ 001 = 101. Every 1-bit of 1 flips that bit of the running value.
  4. 101 ^ 010 = 111. Every 1-bit of 2 flips that bit of the running value.
  5. 111 ^ 001 = 110. Every 1-bit of 1 flips that bit of the running value. 1 appeared before, so this flip undoes the earlier one.
  6. 110 ^ 010 = 100. Every 1-bit of 2 flips that bit of the running value. 2 appeared before, so this flip undoes the earlier one.
  7. The pairs (1 and 1, 2 and 2) cancelled out; only 4 is left. Answer: 4. O(n) time and O(1) space — no hash set needed.

The idea

Numbers are stored as bits, and bitwise operators work on all bits at once. A few facts solve most problems: x ^ x = 0 and x ^ 0 = x; x & 1 is the last bit; x >> 1 drops the last bit; x & (x − 1) removes the lowest set bit.

Picture it

flowchart LR
  A["4 ^ 1 ^ 2 ^ 1 ^ 2"] -->|"reorder freely"| B["4 ^ (1 ^ 1) ^ (2 ^ 2)"] --> C["4 ^ 0 ^ 0"] --> D["4"]
XOR can be reordered, and each pair cancels to 0, leaving only the number without a partner.

Analogy

A row of light switches. XOR with a pattern flips those switches; flipping the same pattern twice puts everything back.

Where the analogy breaks

Switches don't overflow. In Java or C, integers have a fixed number of bits and can overflow; Python integers grow, so problems like Sum of Two Integers need a mask in Python.

More detail

What it is

Deep down, computers don't understand 'Numbers' or 'Strings'. They solely understand 1s and 0s (voltage 'ON' and voltage 'OFF'). Bit Manipulation is the art of bypassing high-level code and directly hacking those raw binary digits! It is insanely fast and requires almost zero memory.

When to use it

  • When asked to find a 'Single Number' in an array of duplicates.
  • When counting the number of '1' bits in an integer.
  • When reversing the binary representation of a number.
  • When doing highly-optimized sets and masks.

How it works

You use special binary operators:\n- & (AND): Returns 1 only if BOTH bits are 1.\n- | (OR): Returns 1 if AT LEAST ONE bit is 1.\n- ^ (XOR): Returns 1 if bits are DIFFERENT. (Crucial rule: X ^ X = 0).\n- << / >> (Shifts): literally slides all bits to the left or right, effectively multiplying/dividing by 2.

Example walkthrough

Input: nums = [4,1,2,1,2]. Find the number that doesn't repeat.

  1. Start with 0.
  2. 0 XOR 4 = 4
  3. 4 XOR 1 = 5
  4. 5 XOR 2 = 7
  5. 7 XOR 1 = 6
  6. 6 XOR 2 = 4.
  7. Because X ^ X = 0, all the duplicate numbers perfectly canceled each other out! The only number left standing is 4.

Result: 4

Related patterns

  • Math & Geometry: Bit manipulation is just math performed in base-2.

Step 2 Recognise it

Words that signal it

  • 'Every element appears twice except one'
  • 'Count the 1 bits', 'reverse the bits'
  • 'Without using + or −'
  • 'Missing number' in 0…n (XOR or the sum formula)

Don't confuse it with

  • Arrays & Hashing: A hash set also finds the single number, but with O(n) memory; XOR does it with O(1).
  • Math: Missing Number can also use n(n + 1)/2 − sum; XOR avoids any overflow worry.

Gut check

Pairs cancelling, single bits, or 'no + allowed'? → bits.

How to recognise it in an interview

The prompt explicitly mentions '32-bit integers', 'Constant space O(1)', or 'Find the missing/single number'.

Step 3 The template

The general shape. Adapt it to each problem rather than learning one solution per problem.

python
def bit_tricks(x):
    last_bit = x & 1               # 1 if x is odd
    x_without_last = x >> 1        # drop the last bit (x // 2)
    lowest_removed = x & (x - 1)   # remove the lowest 1 bit
    count = 0
    while x:
        x &= x - 1                 # one loop per 1 bit
        count += 1
    return last_bit, x_without_last, lowest_removed, count

def single(nums):
    acc = 0
    for x in nums:
        acc ^= x                   # pairs cancel: a ^ a = 0
    return acc
The same template in Java
text
class Solution {
    public int singleNumber(int[] nums) {
        int result = 0;
        for (int num : nums) {
            result ^= num; // XOR magically cancels out any duplicates!
        }
        return result;
    }
}
TimeO(n) or O(number of bits)
SpaceO(1)

Common mistakes

  • Python's ~ and right shifts on negative numbers behave differently from Java's.
  • Forgetting operator precedence: write (x & 1) == 1, with brackets.
  • In Python, not masking with 0xFFFFFFFF when simulating 32-bit integers.
  • Confusing && (Logical AND for booleans) with & (Bitwise AND for bits) in your if-statements.
  • Assuming bitwise operations are readable! They look like gibberish if you don't add comments.

Step 4 Watch it run

Two problems, traced step by step exactly as the code runs.

Easy example: Single Number

Input: nums = [4, 1, 2, 1, 2]

xrunning XOR (in binary)result
4000 ^ 100100 (4)
1100 ^ 001101 (5)
2101 ^ 010111 (7)
1111 ^ 001110 (6)
2110 ^ 010100 (4)

Result: 4

Notice: The order doesn't matter: every number that appears twice cancels itself out.

python
def single_number(nums):
    acc = 0
    for x in nums:
        acc ^= x
    return acc

Medium example: Counting Bits

Input: n = 5

ibinaryrulebits
0000base case0
1001bits(0) + last bit 1 = 0 + 11
2010bits(1) + last bit 0 = 1 + 01
3011bits(1) + last bit 1 = 1 + 12
4100bits(2) + last bit 0 = 1 + 01
5101bits(2) + last bit 1 = 1 + 12

Result: [0, 1, 1, 2, 1, 2]

Notice: i >> 1 is i without its last bit, and you've already counted it. Add the last bit (i & 1) and you're done: O(n) in total.

python
def count_bits(n):
    bits = [0] * (n + 1)
    for i in range(1, n + 1):
        bits[i] = bits[i >> 1] + (i & 1)
    return bits

Step 5 Practise

Read each question and say the pattern and the trick out loud before you open the answer. Then solve it on LeetCode. Tick a problem once you've solved it on your own: it comes back for review tomorrow, then after 3, 7, 14 and 30 days, then every month, on the DSA page.

Easy

  1. Single Number Easy

    Every number appears twice except one; find it with O(1) extra space.

    Show answer

    Technique: XOR

    The clue: Pairs + one leftover + constant space.

    The trick: XOR everything; pairs cancel to 0.

  2. Number of 1 Bits Easy

    Count the 1 bits in an integer.

    Show answer

    Technique: Bit counting with n & (n − 1)

    The clue: 'Count the bits'.

    The trick: n & (n − 1) removes the lowest 1 bit; count how many times until n is 0.

  3. Counting Bits Easy

    For every i from 0 to n, count the 1 bits in i.

    Show answer

    Technique: DP on bits

    The clue: Bit counts for every number up to n, in O(n).

    The trick: bits[i] = bits[i >> 1] + (i & 1).

  4. Reverse Bits Easy

    Reverse the 32 bits of an unsigned integer.

    Show answer

    Technique: Bit-by-bit shifting

    The clue: Work on the binary form directly.

    The trick: 32 times: take n's last bit, shift the result left and add it, shift n right.

  5. Missing Number Easy

    Numbers 0 … n with one missing; find it.

    Show answer

    Technique: XOR (or the sum formula)

    The clue: One missing value from a known complete range.

    The trick: XOR all indexes 0 … n and all values; everything present cancels out, leaving the missing one.

Medium

  1. Sum of Two Integers Medium

    Add two integers without using + or −.

    Show answer

    Technique: XOR for the sum, AND + shift for the carry

    The clue: 'Without + or −'.

    The trick: a ^ b adds without carrying; (a & b) << 1 is the carry; repeat until there's no carry (mask to 32 bits in Python).

  2. Reverse Integer Medium

    Reverse the digits of a 32-bit signed integer, returning 0 if it overflows.

    Show answer

    Technique: Digit popping with an overflow check

    The clue: Digits + a 32-bit limit.

    The trick: Pop the last digit with % 10 and push it onto the result × 10; check the limit before each push.

What to say in the interview

'Since we have a rigid space limitation and are dealing with pairing logic, I can use the XOR operator to cancel out duplicate binary flags.'

Follow-up prep

How do you check if a number is a power of 2 using only bitwise? (Hint: (n & (n - 1)) == 0).