Problem Description
Given a 0-indexed integer array nums, a pair (x, y) is called a strong pair if when letting a = min(x, y) and b = max(x, y) the condition b – a <= a holds. In other words, for any pair chosen from nums, once sorted (x <= y), it must satisfy y <= 2 * x. Note that you can pick the same integer twice. The task is to select two integers from nums such that they form a strong pair and their bitwise XOR is maximum of all strong pairs present, and return that maximum XOR value.
Key Insights
- When x <= y, the condition |x – y| <= min(x, y) can be rewritten as y – x <= x, which simplifies to y <= 2 * x.
- Sorting the array lets us quickly understand the relationship between the smallest and largest in a candidate set.
- If a contiguous subarray (window) in the sorted array satisfies nums[right] <= 2 * nums[left], then every pair in that window satisfies the strong pair condition.
- Using a sliding window along with a bitwise trie (prefix tree) allows us to maintain a dynamic set of candidates and efficiently query for the best XOR partner.
- The trie supports insertion and deletion (by maintaining counts) so that we can “slide” the window while preserving only those numbers that form valid pairs with the current candidate.
- For each new number added, we query the trie to find the number already in the window that produces the highest XOR value with it. Since a valid pair may be formed by a number with itself (yielding 0), we always have a fallback.
Space and Time Complexity
Time Complexity: O(n · B), where n is the length of nums and B is the number of bits (up to 20) since each insert, remove, and query in the trie costs O(B)
Space Complexity: O(n · B) in the worst case for storing numbers in the trie, though typically limited by the range of bits
Solution
- First, sort the array nums.
- Use two pointers (L and R) to maintain a sliding window. The window [L,R] is valid when nums[R] <= 2 * nums[L]; this guarantees that every pair (a, b) within the window is strong.
- Use a trie (bitwise prefix tree) that supports insertion and removal to maintain the numbers in the current window. Each trie node will store a count of how many numbers go through that node so that deletions are possible.
- For each new number at index R:
- Insert nums[R] into the trie.
- While the current window is not valid (i.e. nums[R] > 2 * nums[L]), remove nums[L] from the trie and increment L.
- Query the trie for the best XOR partner of nums[R] (this finds a number in the current window that maximizes nums[R] XOR candidate).
- Update the global maximum XOR value accordingly.
- Finally, return the global maximum XOR value.
This solution leverages both the sliding window technique (to guarantee the strong pair condition across all pairs in the window) and the trie (to efficiently compute the maximum XOR pair in the current valid window).