~20 minutes · Day 5 · XOR cancellation · Python
Tonight's problem is Missing Number. Interviewers like it because the input looks almost too simple: numbers from 0 to n, one missing. The trick is noticing that every number which appears twice can cancel itself away.
x XOR x = 0, so XOR-ing 0..n against the array cancels every present number and leaves the missing one.
Python writes bitwise XOR with ^ (Python docs: binary bitwise operations). The only facts you need are small: x ^ x becomes 0, x ^ 0 stays x, and the order does not matter for XOR (Wikipedia: exclusive or).
The problem: given n distinct numbers taken from the range 0..n, return the one number that is missing. A direct brute force is to test every possible number:
def missing_number(nums):
for want in range(len(nums) + 1):
if want not in nums: # scans the list each time
return want
This is correct, but it is O(n2): there are O(n) possible answers, and want not in nums may scan O(n) items each time. The repeated scan is the cost to remove.
Instead of searching, mix together every number that should exist and every number that does exist. Every present number appears twice in that mix, so it cancels. The missing number appears once, so it survives.
The full range and the array form pairs under XOR; the unpaired value is the missing number.
def missing_number(nums):
ans = len(nums) # include n from the range 0..n
for i, x in enumerate(nums):
ans ^= i # include range value i
ans ^= x # include array value x
return ans # only the missing value remains
For nums = [3, 0, 1], the loop computes 3 ^ 0 ^ 3 ^ 1 ^ 0 ^ 2 ^ 1. The two 3s cancel, the two 0s cancel, the two 1s cancel, and 2 is left.
Imagine a bag of number cards where every value appears exactly twice except one value, which appears once. Before opening the reveal, say the approach out loud: what should the accumulator start as, and what should each step XOR into it?
def lonely_card(cards):
ans = 0
for x in cards:
ans ^= x # pairs cancel: x ^ x = 0
return ans
Same cancellation pattern, slightly easier setup. There is no 0..n range to include, so the accumulator can start at 0 and consume only the array.
| Approach | Time | Space |
|---|---|---|
| Brute force (search every candidate) | O(n2) | O(1) |
| XOR cancellation (one pass) | O(n) | O(1) |
Missing Number also has a sum formula. Learn the XOR version anyway: it teaches the cancellation move that appears in other disguise problems.
1. Which XOR fact powers the trick?
2. Spot the bug in this Missing Number attempt:
ans = 0
for i, x in enumerate(nums):
ans ^= i
ans ^= x
return ans
0..n, but the indexes only give 0..n-1. Starting with len(nums) includes the final range value.3. Which task is an XOR-cancellation fit?
4. In Missing Number, what should be XOR-ed together?
Solve Missing Number in your Notion tracker with the cycle — predict → attempt → compare → encode:
Watch NeetCode — Missing Number at the compare step. Listen for how he decides what must cancel.