Maximum XOR of Two Numbers in an Array
Insert every number's bits into a trie, then greedily flip bits to find its best partner
The highest set bit dominates a number's value more than every lower bit combined, so the best partner for a number is whichever other number disagrees with it as high up as possible. Storing every number's binary form in a 2-child trie lets a query greedily step toward the OPPOSITE bit at each level whenever that branch exists, which is exactly how to build the largest possible XOR one bit at a time. 5 and 25 (00101 and 11001) disagree on every single bit, so tracing just those two shows the full algorithm: they build separate branches, and querying 5 walks straight down 25's branch for the maximum possible result, 28.
Details
Animated on: Given nums = [3, 10, 5, 25, 2, 8], find the maximum XOR of any two numbers in the array.
Problem:Maximum XOR of Two Numbers in an ArrayMedium
Insert every number's bits into a trie, then greedily flip bits to find its best partner
step 1 / 9
Every value in nums gets inserted into a trie of its 5-bit binary form, most significant bit first. Start with just a root.
1FUNCTION insert(root, num):2 node <- root3 FOR b FROM 4 DOWNTO 0:4 bit <- BIT(num, b)5 IF node.children[bit] = NULL: node.children[bit] <- NEW NODE6 node <- node.children[bit]7 node.end <- TRUE8FUNCTION bestPartner(root, num):9 node <- root, ans <- 010 FOR b FROM 4 DOWNTO 0:11 bit <- BIT(num, b), want <- 1 - bit12 IF node.children[want] != NULL: ans <- 2*ans + 1, node <- node.children[want]13 ELSE: ans <- 2*ans, node <- node.children[bit]14 RETURN ans
← / → step · space play · Home restart
Every step in words
Show all 9 steps
- Every value in nums gets inserted into a trie of its 5-bit binary form, most significant bit first. Start with just a root.
- insert(5): 5 in binary is 00101. No node existed yet, so all 5 bits create a brand-new chain, and the last node is marked as an END (it stores the value 5).
- insert(25): 25 in binary is 11001. Its very first bit (1) already differs from 5's first bit (0), so 5 and 25 share NO prefix at all — 25 grows an entirely separate branch off the root.
- bit 4 of 5 is 0, so the opposite bit 1 is what we want. A child for 1 exists — follow it. Running XOR so far: 1 (decimal 1).
- bit 3 of 5 is 0, so the opposite bit 1 is what we want. A child for 1 exists — follow it. Running XOR so far: 11 (decimal 3).
- bit 2 of 5 is 1, so the opposite bit 0 is what we want. A child for 0 exists — follow it. Running XOR so far: 111 (decimal 7).
- bit 1 of 5 is 0, so the opposite bit 1 is what we want, but no child for 1 exists here. Fall back to the only link available (bit 0). Running XOR so far: 1110 (decimal 14).
- bit 0 of 5 is 1, so the opposite bit 0 is what we want, but no child for 0 exists here. Fall back to the only link available (bit 1). Running XOR so far: 11100 (decimal 28).
- The walk ends on the END node for 25 — every level found (or fell back to) a real link, so this is a genuine pair. 5 XOR 25 = 28, matching the trie's own answer of 28. Querying every number the same way and keeping the largest result is the whole algorithm.
Now solve it yourself
Watching is the first half. The second is writing it without the animation.