Home › DSA Patterns › Bit Manipulation
B

Bit Manipulation

Master a handful of bit tricks and problems that look like puzzles collapse into two-line answers. This topic quietly sorts people who memorized tricks from people who understand how numbers are stored, and the second group walks away looking sharp. The real test is almost never "use bits." It is hearing "O(1) space" or "the array is tiny" and knowing that is the invitation.

DSA PatternsMedium11 min read
Who asks this, and how oftenInterview frequency: Common

Most asked at Microsoft. Here is how often this pattern shows up in each company's coding rounds.

Microsoft
74
Amazon
72
Google
70
Apple
68
Meta
64
Relative frequency index from 0 to 100, based on commonly reported interview experiences. Use it as a guide to where this pattern pays off most, not an exact count.

If you remember five things

Eight ideas run this whole topic. These five are the ones you reach for first.

  1. XOR cancels itself. a ^ a = 0 and a ^ 0 = a, so pairs vanish and the loner survives. Half the famous bit problems are this one idea in disguise.
  2. An int is a set of flags. A 32-bit integer is 32 free boolean flags, so a constraint like n up to 20 is the bitmask-as-a-set signal.
  3. Four templates, drilled cold. Test, set, clear, toggle a bit. Fumbling set versus clear under pressure silently returns garbage with no error.
  4. Two low-bit moves. x & (x - 1) turns off the lowest set bit, x & (-x) isolates it. These power counting and splitting.
  5. Say why it works. "Pairs cancel because a XOR a is zero" is most of the interview. Skip it and you look like you copied a cheat sheet.

1The mental model (what this really is)#

An integer is a fixed row of switches, nothing more.

  • A 32-bit int is 32 switches, a 64-bit long is 64. Each switch (a bit) is 0 or 1.
  • Place values go right to left: 1, 2, 4, 8, 16, and so on. That is just base 2.
  • So 13 is 1101: one 8, one 4, zero 2s, one 1.

Bit manipulation means working the switches directly instead of treating the number as one value. You flip them, test them, shift them left and right, and combine two rows with logical operators.

Four operators do almost all the work:

  • & (AND): a bit is 1 only if both inputs are 1. Tests a bit or clears bits. 1101 & 0100 = 0100.
  • | (OR): a bit is 1 if either input is 1. Sets bits. 1101 | 0010 = 1111.
  • ^ (XOR): a bit is 1 if the inputs differ. The magic one. Toggles, pairs, and cancels. 1101 ^ 0110 = 1011.
  • ~ (NOT): flips every bit. ~0000 = 1111 within the width you are working in.

Two shifts move whole rows:

  • x << k multiplies by 2 to the power k (pushes bits left, fills zeros on the right). 1 << 4 is 16.
  • x >> k divides by 2 to the power k (pushes bits right). 48 >> 2 is 12.
The one fact to burn in first

XOR cancels itself: a ^ a = 0, and a ^ 0 = a. XOR a pile of numbers together and everything that appears an even number of times cancels to zero. Whatever is left standing is the odd one out. Learn this before anything else, because it is the engine behind most of the famous problems.

2How to recognize it (the signals in a problem)#

You are looking at a bit problem the moment you see one of these cues. Interviewers rarely say "bits," so train on the phrasing instead.

  • Numbers appearing an even or odd number of times, or "every element appears twice except one." That is XOR, almost always.
  • A small fixed set (roughly up to 20 or 32 items) where you track which ones are used. A 32-bit int is a free set of 32 flags. The giveaway is a constraint line like 1 <= n <= 20.
  • "Count set bits," "find a power of two," "swap without a temp," or "add without +, -, *, /." That phrasing is an explicit invitation.
  • Numbers near a power of two, or ranges like 0 to 2^n, where binary structure matters.
  • "Enumerate all subsets of a set." Loop an integer from 0 to 2^n and read its bits.
  • "Can you do this in O(1) space" right after you gave a hashmap answer. Nine times out of ten they want XOR.
Red flag that costs you the round

Forcing a bit trick on a problem that wants a hashmap. If there is no count, no subset, and no binary structure, do not reach for XOR. It is a classic way to overcomplicate and burn fifteen minutes you did not have. Clean and working beats clever and broken.

3The template (how it works, with pseudocode)#

Keep these building blocks in muscle memory. I rewrite them from scratch on scratch paper before every interview, because they are easy to fumble under pressure and a wrong & versus | silently returns garbage with no error.

# Read the i-th bit (0 = rightmost)
bit = (x >> i) & 1

# Set the i-th bit to 1
x = x | (1 << i)

# Clear the i-th bit to 0
x = x & ~(1 << i)

# Toggle the i-th bit
x = x ^ (1 << i)

# Check if a number is a power of two (and not zero)
is_power = x > 0 and (x & (x - 1)) == 0

# Turn off the lowest set bit
x = x & (x - 1)

# Isolate the lowest set bit
lowest = x & (-x)

# Count set bits (Brian Kernighan: loops once per set bit)
count = 0
while x:
    x = x & (x - 1)
    count += 1

Two of these deserve a pause.

  • x & (x - 1) clears the lowest 1 bit. Subtracting 1 flips the lowest 1 to 0 and turns every 0 below it into 1, so AND-ing wipes that whole low section down to the next 1. Example: 12 = 1100, 11 = 1011, and 1100 & 1011 = 1000. The lowest 1 is gone.
  • x & (-x) isolates the lowest 1. In two's complement, -x is the bit-flip of x plus 1, which lines up exactly at that lowest bit and nowhere else. For 12, x & (-x) gives 100, which is 4, the value of that lowest set bit.

For subset enumeration, the frame is:

for mask in range(0, 1 << n):   # every possible subset of n items, 2^n of them
    for i in range(n):
        if (mask >> i) & 1:      # item i is in this subset
            # use item i
  • The outer loop runs 2^n times, once per subset.
  • The inner loop reads each of the n bits to see which items the current mask includes.
  • For n = 20 that is about a million masks, which runs comfortably.
  • For n = 30 it is a billion and you are already in trouble, which is exactly why the constraint on n is your signal.
Pause before the worked example: you are handed an array where every number appears twice except one, and the prompt says "constant extra space." What is the hint actually telling you to drop?
Reveal the answer
Drop the hashmap. A counting map is O(n) space, and "constant space" is screaming that pairs can cancel instead of being counted. The fix is XOR the whole array: every pair cancels to zero, the loner survives, one integer of memory. Hearing that from "constant space" alone is the skill this topic grades.

4A worked example (walk through one problem step by step)#

Classic prompt: given an array where every number appears exactly twice except for one number that appears once, find the single number. Linear time, constant extra space.

  • My first instinct as a beginner was a hashmap counting occurrences. That works, it is O(n) time, but it uses O(n) space, and the "constant space" hint is screaming that there is something cleaner.
  • The key observation: we want pairs to disappear and the loner to survive. XOR does exactly that. Any value XOR'd with itself is 0.
  • So if I XOR every element together, each pair cancels to 0, and the one unpaired value is left standing.

Run it on [4, 1, 2, 1, 2], starting with an accumulator ans = 0:

  • ans = 0 ^ 4 = 4. In bits, 0000 XOR 0100 is 0100.
  • ans = 4 ^ 1 = 5. 0100 XOR 0001 is 0101.
  • ans = 5 ^ 2 = 7. 0101 XOR 0010 is 0111.
  • ans = 7 ^ 1 = 6. 0111 XOR 0001 is 0110. The first 1 just got cancelled.
  • ans = 6 ^ 2 = 4. 0110 XOR 0010 is 0100. The first 2 just got cancelled.

Final answer: 4. The two 1s cancelled each other, the two 2s cancelled each other, and 4 stood alone.

Why order did not matter:

  • XOR is commutative and associative, so a ^ b = b ^ a and the grouping is free.
  • Shuffle that array any way you like and the pairs still find each other and vanish.
  • That property is why this works in one pass with a single variable, no sorting required.
ans = 0
for num in array:
    ans = ans ^ num
return ans

One pass, one integer of memory. Deliver this after first naming the hashmap version and you show you know both and chose the better one on purpose. That reads as judgment, not luck, and judgment is what the round is grading.

Name the hashmap, then beat it with XOR. Knowing both is the signal; picking the better one is the point.

5Variations and gotchas#

Once you own the single-number idea, interviewers twist it:

  • Every number twice except two singles. XOR everything to get a ^ b. That combined value has a 1 in every bit position where a and b differ. Isolate any one of those differing bits with diff & (-diff), then split the array into two groups by whether each element has that bit set, and XOR each group separately. a lands in one group, b in the other, each surviving alone. This is Single Number III.
  • Every number three times except one. XOR no longer works, because three copies of a value do not cancel to zero. Instead, count bits per position across all numbers; each position's count mod 3 reconstructs the answer bit by bit. Or use two accumulators (ones and twos) that simulate counting mod 3 in a single pass.
  • Bitmask dynamic programming. Problems like assigning n tasks to n people, or the traveling salesman on a small graph, use an integer mask to represent "which items are used so far." The state is dp[mask], and you transition by setting one more bit. This is where bit manipulation meets DP, and it is the home of the hard problems on this topic.
  • Swap two values with no temp: a ^= b; b ^= a; a ^= b. Cute, rarely needed, breaks if a and b are the same memory location, good to know it exists.

Gotchas that bite people:

  • Signed integers and the sign bit. In 32-bit and 64-bit languages the top bit means negative. Right-shifting a negative number may copy the sign bit (arithmetic shift) instead of filling zeros, so -8 >> 1 is not what a naive reader expects. In Java use >>> for an unsigned shift that fills zeros. In Python integers are arbitrary precision, so there is no fixed 32-bit wrap unless you mask with & 0xFFFFFFFF.
  • Operator precedence. x & 1 == 0 does NOT mean what you think. == binds tighter than &, so this parses as x & (1 == 0), which is x & 0, which is always 0. Always parenthesize: (x & 1) == 0. I have watched strong candidates lose ten minutes chasing this exact bug on a whiteboard.
  • 1 << i overflow. For large i in a fixed-width language, shift a 64-bit literal, not a 32-bit int. In Java write 1L << 40, not 1 << 40, or you get silent garbage once i hits 31.
From the interviewer's chair

When a candidate hits Single Number III, I watch for the differing-bit split. Most people stall at a ^ b and freeze, because they cannot see how to separate the two survivors. Saying "isolate any bit where they differ with diff & (-diff), then partition" out loud, before writing code, tells me you understand the structure rather than pattern-matched the easy case.

6Complexity#

Single-pass bit solutions are the whole selling point over the hashmap.

  • Most are O(n) time and O(1) space, where n is the array length. That O(1) space is the win, so say it out loud.
  • Operations on a single integer (test, set, shift, Kernighan's count) are O(w) where w is the word width, usually 32 or 64. Since w is a fixed constant, people call these O(1).
  • Kernighan's set-bit count runs once per set bit, so it is O(number of set bits), which beats checking all 32 positions when the number is sparse.

Subset and bitmask work is exponential by nature, and that is fine when n is small.

  • Subset enumeration is O(2^n) just to list the subsets, times another factor for whatever you do inside each one.
  • Bitmask DP is typically O(2^n * n) or O(2^n * n^2).
  • These only work because n is tiny, usually at most 20 or so (2^20 is about a million states).
  • That small constraint on n is your signal to reach for a mask instead of a hashset of visited states.

7Mistakes that cost people the round#

  • Forcing bits where a hashmap is cleaner. No count, subset, or binary structure means XOR is not the answer. Do not look clever at the cost of a working solution before the clock runs out.
  • The precedence bug above. Parenthesize every bit expression. Say it out loud as you write it: "x and one, close paren, equals zero."
  • Fumbling the templates. Mixing up set versus clear, or writing x | (1 << i) when you meant to clear with x & ~(1 << i). Drill these until they are automatic. An interviewer loses faith fast when the basics wobble, because it signals you memorized rather than understood.
  • Ignoring the sign bit and overflow. Know your language's shift behavior cold. In Java or C++, mention unsigned shift and 64-bit literals before they have to ask.
  • Not explaining why XOR works. Writing the one-liner is not enough. Say "pairs cancel because a XOR a is zero, so only the unpaired value survives." That one sentence is most of the interview. Skipping it makes you look like you memorized a trick off a cheat sheet.
  • Off-by-one in masks. Items are indexed 0 to n-1, and the subset loop goes 0 to 2^n - 1. Mixing those bounds up corrupts the whole enumeration and is painful to spot after the fact.

8Your practice path (named problems by difficulty)#

Do them in this order. The early ones build the reflexes the later ones assume. I would not touch the Hard tier until the Easy list feels boring.

Warm-up (Easy):

  • Number of 1 Bits
  • Single Number
  • Power of Two
  • Reverse Bits
  • Counting Bits
  • Hamming Distance
  • Complement of Base 10 Integer

Core (Medium):

  • Single Number II (every element three times except one)
  • Single Number III (two unique elements)
  • Sum of Two Integers (add without + or -)
  • Bitwise AND of Numbers Range
  • Subsets (enumerate with bitmasks)
  • Maximum XOR of Two Numbers in an Array
  • Gray Code
  • Divide Two Integers

Stretch (Hard, bitmask DP):

  • Partition to K Equal Sum Subsets
  • Shortest Path Visiting All Nodes
  • Minimum Cost to Connect Two Groups of Points
  • Maximum Students Taking Exam

If you only have one evening, do Single Number, Number of 1 Bits, Counting Bits, Subsets, and Single Number III. Those five cover the ideas behind most of the rest: XOR cancellation, Kernighan counting, DP over bit counts, mask enumeration, and the split-by-differing-bit trick.

9Where this shows up (which companies and rounds lean on it)#

Bit tricks live in the quick-filter rounds.

  • They show up most in phone screens and early onsite rounds, especially at companies that love clean micro-optimizations: Amazon, Google, Microsoft, Apple, and the trading and systems firms where bits map to real hardware.
  • The XOR single-number family is a perennial warm-up you should expect to see cold.
  • Bitmask DP tends to appear in harder onsite rounds at Google and competitive-programming-flavored teams, where a problem reads like TSP on eight nodes.
  • Embedded, graphics, and low-level systems roles use set, clear, and test bits as everyday bread and butter, so expect them throughout those interviews even when the rest of the loop is standard.

The pattern rarely carries a whole interview on its own. More often it is the elegant twist on a larger problem, or the O(1)-space upgrade an interviewer nudges you toward after your first hashmap answer. Recognizing that nudge, and reaching for XOR the moment you hear "constant space," is the real skill this topic is testing.

Follow-ups the interviewer will ask (and your answers)
"Same problem, but every number appears three times except one. Does XOR still work?"
No. Three copies of a value do not cancel, so a ^ a ^ a leaves a, not zero. I count bits per position across all numbers and take each position's count mod 3 to rebuild the answer bit by bit, or carry two accumulators (ones and twos) that simulate mod-3 counting in a single O(n) pass.
"Now two numbers appear once and everything else twice. Find both."
XOR everything to get a ^ b. That value has a 1 in every bit where a and b differ, so I isolate one such bit with diff & (-diff), split the array into two groups by whether each element has that bit set, and XOR each group. a and b land in different groups, so each survives alone. That is Single Number III.
"You wrote x & 1 == 0 to test even. Are you sure?"
That is the precedence trap. == binds tighter than &, so it parses as x & (1 == 0), which is x & 0, always 0. I always parenthesize: (x & 1) == 0. It is a silent bug with no error, so I say it out loud as I write it.
"Right-shifting a negative number gives weird results. Why?"
The top bit is the sign, and most languages do an arithmetic right shift that copies the sign bit instead of filling zeros, so -8 >> 1 stays negative. In Java I use >>> for an unsigned shift. In Python integers are arbitrary precision, so I mask with & 0xFFFFFFFF when I need fixed-width behavior.
"Why does the n up to 20 constraint point at a bitmask?"
A bitmask over subsets is 2^n states. At n = 20 that is about a million, which runs comfortably, so a 32-bit int becomes a compact "which items are used" set for DP. Past roughly n = 30 it is a billion and the approach dies, so the small n in the prompt is the signal to reach for the mask.

What you can now explain in the room

  • Why XOR cancellation finds the single number in one pass with O(1) space.
  • How to read the signals (counts, subsets, binary structure, "constant space") that mean bits.
  • The four core templates (test, set, clear, toggle) and why you parenthesize every one.
  • What x & (x - 1) and x & (-x) do, and why, in two's complement terms.
  • How the differing-bit split solves Single Number III, and why three-times needs mod-3 counting.
  • Why n up to 20 means a bitmask, and what 2^n and 2^n * n complexity really cost.

Want to see which companies lean on bit tricks and in which rounds? Check the company guides to map this pattern to real interview loops.

Get a prep plan built around your Bit Manipulation interview

Tell us the role and your interview date. We will send back a dated, day by day plan. Free.

Thanks. Check your inbox, your Bit Manipulation prep plan is on the way.