The Quest Begins (The "Why")
I still remember the sweat on my palms during my first technical interview. The interviewer slid a simple prompt across the table: “Given an array where every element appears exactly twice except for one, find that single element.” My brain jumped to the obvious solution – dump everything into a hash map, count frequencies, then scan for the odd one out. It worked, but the interviewer raised an eyebrow and asked, “Can you do it in O(1) extra space?” I felt like a rookie facing the final boss without a power‑up. That moment sparked a quest: I needed a trick that could strip away the noise using nothing but the numbers themselves.
The Revelation (The Insight)
The answer was hiding in a operation most of us treat as a low‑level curiosity: XOR (exclusive‑or). At first glance XOR looks like just another bitwise gate, but its properties are pure magic for this problem.
-
Self‑cancellation:
a ^ a = 0. Any number XOR‑ed with itself disappears. -
Identity:
a ^ 0 = a. Zero leaves a number untouched. - Commutative & Associative: The order doesn’t matter; you can fold the operation however you like.
Why does that help? Imagine writing each number in binary and adding the bits column‑wise, but ignoring carries – that’s exactly what XOR does per bit. If a bit appears an even number of times across the whole array, those 1s cancel out to 0. If it appears an odd number of times, a single 1 remains. In our array every duplicated element contributes an even count (two) for each of its bits, so they all vanish. The lone element contributes an odd count (one) for each of its bits, and those survive the cancellation. The final XOR of the whole array is therefore the unique number.
It’s like watching a crowd of people wearing identical hats walk into a room, pair up, and leave – only the person with the weird hat stays behind. The hat is the bit pattern of the answer.
Wielding the Power (Code & Examples)
The Struggle (Hash‑Map Approach)
def single_number(nums):
freq = {}
for x in nums:
freq[x] = freq.get(x, 0) + 1
for x, cnt in freq.items():
if cnt == 1:
return x
Pros: Simple to read.
Cons: O(n) extra space for the hash map, and two passes over the data. In an interview setting, that extra space often raises red flags.
The Victory (XOR Trick)
def single_number(nums):
result = 0
for x in nums:
result ^= x # <-- the spell
return result
Why it works:
- Start with
result = 0(the identity). - Each iteration XOR‑s the current number into
result. - Pairs cancel (
a ^ a = 0), leaving only the unpaired value. - One pass, O(1) auxiliary memory, O(n) time.
Common Trap #1 – Forgetting the Initial Zero
If you start result = nums[0] and then loop from index 1, you’ll still get the right answer, but you lose the beautiful symmetry of the identity property and risk off‑by‑one errors when the array length is 1. Starting at zero is the cleanest, most idiomatic form.
Common Trap #2 – Assuming It Works for Any Duplication Count
The XOR trick only cancels when every other element appears an even number of times. If the prompt said “three times each except one”, you’d need a different bit‑wise state machine (still O(1) space but more involved). Knowing the limits of your tool keeps you from trying to force a square peg into a round hole.
A Second Interview Flavor – Missing Number
Another classic: “Given an array nums containing n distinct numbers taken from 0, 1, 2, …, n, find the missing one.”
Same principle! XOR all indices 0…n together with all array values; every present number cancels with its index, leaving the gap.
def missing_number(nums):
n = len(nums)
xor_all = 0
for i in range(n + 1):
xor_all ^= i # XOR of 0…n
for x in nums:
xor_all ^= x # XOR of array elements
return xor_all
Again, one pass over indices, one pass over values, O(1) space.
Why This New Power Matters
Mastering the XOR trick does more than solve a single interview puzzle. It reshapes how you think about data: you start seeing problems as parity checks rather than frequency counts. Suddenly, you can:
- Detect a single corrupted bit in a stream with O(1) memory.
- Swap two variables without a temporary (
a ^= b; b ^= a; a ^= b;). - Compute the XOR of a range in O(1) using prefix patterns (
f(n)repeats every 4). - Build elegant solutions for sub‑array XOR queries, Nim‑game theory, and even certain cryptographic primitives.
In short, you’ve added a versatile, low‑overhead tool to your belt—one that runs faster than a hash map, needs no extra allocation, and feels like uncovering a secret cheat code.
Your Turn – The Challenge
Grab a piece of paper (or your favorite IDE) and try this:
Given an array where every element appears exactly three times except for one that appears once, find that single element.
Hint: you’ll need to count bits modulo 3, but you can still do it with O(1) space using two bit‑masks. Give it a shot, then compare your solution to the classic “bitwise state machine” answer.
If you crack it, drop a comment with your approach—or share a “wait, that actually works!” moment. Happy bit‑twiddling, and may your XOR be ever in your favor! 🚀
Top comments (0)