The loner

Nine numbers sit in an array. Eight of them have exact duplicates somewhere in the list — four pairs, neatly matched. But one number has no partner. It appears exactly once.

3735975

This problem — “find the single unique element” — shows up everywhere. It's LC 136, one of the most-asked easy problems, and it's also the foundation for harder variants like “single number II” and “single number III.” The naive solutions are straightforward, but the elegant solution uses a technique you've already mastered.

Your task is to find the loner. At first, the only tool you have is your eyes. Scan the array below and spot it.

Tap the number that has no partner.

You found it by visual scanning — comparing each number against every other. That's essentially an O(n^2) brute force or an O(n) hash set approach. Both work, but both cost something: either time or space. What if you could find the unique element with zero extra memory?

The expensive way

The most natural solution is a Set: iterate once, adding unseen values and removing seen ones. Whatever remains is the loner. The code writes itself — something like const seen = new Set() followed by a loop that toggles membership. It works perfectly: O(n) time, O(n) space.

But that space cost is real. For an array of a million elements, you're allocating a million-entry hash table just to find one number. Every set.add() call is a hash computation, a memory allocation, a pointer chase. The algorithmic complexity is fine, but the constant factors add up — and the O(n) memory is fundamentally unnecessary.

O(n) spaceaccO(1) space

There's a way to do this with a single integer variable and zero extra memory. It relies on everything you learned about XOR in the previous module. Watch both approaches race side by side.

Predict how much memory a hash set needs for 1 million elements.

Array of 1,000,000 integers. How much memory does a hash set need to find the unique?

The hash set works but burns O(n) memory. The XOR fold uses O(1) — a single accumulator variable. That's not a minor optimization; it's a fundamentally different approach to the problem. The question is: why does it work?

Annihilate the array

The space race showed the mystery approach using O(1) memory — a single integer variable, 4 bytes, no hash table. But how can a single integer possibly track which elements have partners and which don't? The hash set approach needs an entire data structure for that bookkeeping.

What happens if you XOR every element in the array into a single accumulator, one at a time? The XOR laws you built in the previous module — self-inverse, identity, commutativity — are about to do something remarkable. But you need to see it unfold step by step to believe it.

XOR fold

Fold the array below and predict what happens at each step. Watch the accumulator carefully — can you spot the moment a pair cancels? Can you predict what the final value will be before you finish?

Folded 1 of 5 elements. Accumulator: 4.
Space:4 bytes
40100
10001
20010
10001
20010
Accumulator
=4
Fold step 1: XOR accumulator with 1

The pairs vanished and the loner survived. No hash table, no sorting, no nested loops — just one pass through the array with a running XOR. The algebra you built in the previous module isn't abstract theory; it's a concrete algorithm that runs in O(n) time and O(1) space.

Now you drive

Same principle, new array. This time you choose the fold order. Does it matter?

0 of 5 elements folded. Accumulator: 0. Tap any remaining element to fold it.
Tap elements in any order you like.
Accumulator
=0

No matter how you ordered the fold, the same element survived. Commutativity and associativity aren't just theoretical properties — they're what make XOR-fold robust against any input ordering. You don't need to sort, partition, or preprocess. Just fold.

What's missing?

A different problem with the same tool — but a twist that reveals how flexible XOR-fold really is. The previous screens found a unique element in an array of duplicates. This problem has no duplicates at all: you're given the numbers 0 through n, but one is missing. You have n numbers instead of n+1. Can XOR find the gap?

The naive approach is summation: compute expected = n*(n+1)/2, subtract the array sum, and the difference is the missing number. That works, but it risks integer overflow for large n — the sum can exceed 32-bit bounds. XOR doesn't have that problem, because XOR-folding never grows beyond the bit width of the largest input.

But XOR-fold worked before because duplicates cancelled. This array has no duplicates — every number appears exactly once (except the missing one). How would you create pairs to cancel? Think about what additional information you have: you know what the complete range 0..n should contain. Can you use that knowledge to manufacture the pairs XOR needs?

array0..n001123344
Predict whether XOR fold can find a missing number.
Array 013 is missing a number from range 0..3.

Can XOR fold find the missing number?

XOR-fold found the missing number by cancelling every present value against its expected counterpart. The same O(1) space, O(n) time guarantee. This variant appears as LC 268 — and the one-liner solution is a direct translation of the fold you just performed.

In code

Both algorithms — find-the-unique and find-the-missing — reduce to nearly identical TypeScript. The unique-element finder is arr.reduce((acc, x) => acc ^ x, 0). The missing-number variant XOR-folds the array and then XOR-folds the expected range 0..n, returning whatever doesn't cancel. Build both functions and see how the algebraic insight compresses into minimal code.

Fill in the blanks to complete the singleNumber function.
function singleNumber(nums: number[]): number {
let result =  
for (const n of nums) {
result = result n
}
return
}

Two functions, two reduce calls. The conceptual work happened in the algebra module — the code is just the final translation. This is the pattern with bitwise algorithms: the understanding is the hard part, and the implementation is almost free once you have it.

Where does this work?

XOR-fold is elegant but not universal. It requires every element to appear an even number of times except the target. If three values appear once and two appear twice, the fold gives you the XOR of all three singletons — useful, but not a single answer. Similarly, if a value appears three times, it doesn't fully cancel (a ^ a ^ a = a). Identify which problems are XOR-safe and which break the assumption. Knowing the boundary is as important as knowing the trick.

evena^aoddaaa^^
Folding trap array. 1 of 7 elements folded.
2
2
3
3
3
5
5
Accumulator
=2
Fold step 1: XOR accumulator with 2

Finding the Unique

The Lonervisual scanidentified the unique
Space Racehash set vs XOR fold8 MB vs 4 bytes
Array Foldmidpoint + guarantee gatespredicted cancellation
Independent Foldcommutativity + triple-count queryorder independence proven
Missing Numberarray + range = missing revealeddual fold mastered
Code BridgesingleNumber + missingNumber2 functions built
Pattern Boundaryeven-count invariant discoveredtrap survived
You started with a visual puzzle -- one number with no partner. Then you felt the COST: 8 MB for a hash set vs 4 bytes for a single variable. The array fold made cancellation concrete: you watched pairs vanish bit by bit, with the unique element surviving alone. The guarantee came from the algebra, not the specific values. You drove the fold yourself in any order, proving commutativity is not just a property -- it is a practical freedom. Then the triple-count question sharpened the boundary. The missing number variant extended the technique: fold the array AND the range. Present elements cancel across both folds. The gap survives. Finally, the trap. The fold SAID 3, but 3 appeared three times. That failure taught you the real invariant: non-target elements must appear an EVEN number of times.

Hash set vs XOR fold

1
// Hash set: O(n) space
2
function singleNumber_hash(nums: number[]): number {
3
  const seen = new Set<number>()
4
  for (const n of nums) {
5
    if (seen.has(n)) seen.delete(n)
6
    else seen.add(n)
7
  }
8
  return [...seen][0]
9
}
10
11
// XOR fold: O(1) space
12
function singleNumber(nums: number[]): number {
13
  let result = 0
14
  for (const n of nums) result ^= n
15
  return result
16
}

When to reach for XOR fold

Single uniqueEvery element appears twice except one unique element
Missing numberFind the gap in a range 0..n with one value absent
Boundary checkVerify non-target elements appear an EVEN number of times