Problem Statement
Maximum XOR of Two Numbers
You are given a list of non-negative whole numbers. Pick any two of them and XOR them together. XOR is a way of comparing two numbers bit by bit: at each position, the result bit is 1 when the two input bits are different, and 0 when they are the same. So XOR rewards differences. Your job is to find the pair whose XOR is the largest possible, and return that value. The clever tool for this is a trie. A trie is like a branching tree of choices, the same way a phone keypad word-finder narrows down letter by letter. Here each number is spelled out in its bits, from the biggest bit down to the smallest, and each bit (0 or 1) is one fork in the road. Once every number lives in the trie, we walk it for each number and, at every fork, we try to go the opposite way, because opposite bits give a 1 in XOR, and a 1 in a high position is worth a lot.
Signals to notice
Brute force first
XOR every pair — O(n²).
The key insight
Binary trie (MSB to LSB). For each number, walk trie choosing opposite bit at each level. O(32n).
Trace it on nums=[3,10,5,25,2,8]
Build binary trie: insert all 6 numbers bit-by-bit MSB->LSB. 5-wide bits: 3=00011, 10=01010, 5=00101, 25=11001, 2=00010, 8=01000 Query num=3 (00011): greedy opposite-bit walk -> diverges toward 25's high bits, curr=11010=26 (3 XOR 25). best=26 Query num=10 (01010): opposite-bit walk -> best reachable curr=10011=19. best stays 26 Query num=5 (00101): opposite-bit walk finds 25 (11001) path -> curr=11100=28 (5 XOR 25). best=28 Query num=25 (11001): opposite-bit walk finds 5 (00101) -> curr=11100=28. best stays 28 Query num=2 (00010) -> curr=11011=27; num=8 (01000) -> curr=10001=17; both <=28, best unchanged Return best = 28 (5 XOR 25 = 28)
What must stay true
Opposite bits maximize XOR. Trie enables greedy bit-by-bit maximization in O(32) per number.
Shape of the loop
build trie: for each num, insert its bits MSB→LSB (2 children per node)
best = 0
for num in nums:
node, curr = root, 0
for i from high_bit down to 0:
want = opposite of num's bit i
if want in node: curr |= (1<<i); node = node[want] # took divergent path
else: node = node[num's bit i]
best = max(best, curr)
return bestPseudocode only — the full worked solution lives in the Solution tab.
Easy way to go wrong
Using decimal trie — it's a BINARY trie with 2 children per node.