Find the subarray with the max XOR from an array using a trie
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The maximum XOR subarray problem asks for a contiguous segment of an array whose XOR value is as large as possible. The efficient solution uses prefix XOR values and a binary trie, reducing the problem from checking every subarray to querying the best earlier prefix for each position.
Why Prefix XOR Solves the Subarray Part
Let prefix[i] be the XOR of all elements from index 0 through index i.
Then the XOR of subarray l..r is:
prefix[r] XOR prefix[l - 1]
That is the same trick used in sum-prefix problems, except XOR replaces addition and subtraction.
So if you are at position r, the best subarray ending at r comes from finding an earlier prefix value that maximizes:
prefix[r] XOR earlier_prefix
This transforms the original problem into a repeated "find the best XOR partner" problem.
Why a Binary Trie Helps
A binary trie stores integers bit by bit. For a maximum XOR query, the greedy idea is simple:
- if the current bit is
0, you prefer a stored1 - if the current bit is
1, you prefer a stored0
That is because 1 XOR 0 = 1 and 0 XOR 1 = 1, which gives a larger contribution at that bit position.
By walking the trie from the most significant bit down to the least significant bit, you can build the maximum possible XOR against the values already inserted.
The Full Approach
The algorithm is:
- initialize prefix XOR to
0 - insert
0into the trie before processing the array - for each array element, update the running prefix XOR
- query the trie for the best XOR partner
- update the answer if this XOR is larger
- insert the new prefix XOR into the trie
Inserting 0 at the start is important because it allows subarrays beginning at index 0 to be considered naturally.
Python Implementation
The following code returns both the maximum XOR value and the subarray boundaries.
For this input, the best subarray is the one whose XOR value is largest among all contiguous segments.
Why the Trie Query Is Correct
The trie query is greedy from the highest bit downward. That works because a larger decision at a more significant bit always dominates any later decisions at lower bits.
For example, getting a 1 at bit position 8 is more valuable than anything you can do with bits 7 through 0. So the best strategy is always to try the opposite bit first at each level.
That is why the trie solution runs in linear time with respect to the number of array elements, assuming a fixed integer width.
Complexity
If integers are treated as fixed-width, for example 32 bits:
- insertion is
O(32) - query is
O(32) - total time is
O(n) - trie storage is
O(32 * n)in the worst case
In practice, that is usually described as linear time because the bit width is constant.
Handling Negative Numbers
If the array can contain negative numbers, you must be careful because Python integers do not have fixed-width two's complement behavior by default. One common approach is to mask values to a fixed width such as 32 bits.
For many interview-style versions of the problem, the array is assumed to contain non-negative integers, which avoids that complication.
Common Pitfalls
The most common mistake is forgetting to insert the initial prefix XOR value 0. Without it, subarrays starting at index 0 are missed.
Another issue is inserting the current prefix before querying. That can let the algorithm compare the prefix against itself and accidentally consider an empty subarray.
People also often compute the maximum XOR value but forget to track which earlier prefix produced it. If you need the actual subarray boundaries, store the prefix index in the trie.
Finally, negative integers require explicit bit-width handling. The simple version of the trie solution assumes fixed-width non-negative values.
Summary
- A subarray XOR can be written as the XOR of two prefix XOR values.
- The problem becomes finding the best earlier prefix for each current prefix.
- A binary trie supports fast maximum-XOR queries bit by bit.
- Insert
0first so subarrays starting at index0are included. - Store prefix indexes in the trie if you need the actual subarray, not just the XOR value.

