Welcome to Subscribe On Youtube
1707. Maximum XOR With an Element From Array
Description
You are given an array nums
consisting of non-negative integers. You are also given a queries
array, where queries[i] = [xi, mi]
.
The answer to the ith
query is the maximum bitwise XOR
value of xi
and any element of nums
that does not exceed mi
. In other words, the answer is max(nums[j] XOR xi)
for all j
such that nums[j] <= mi
. If all elements in nums
are larger than mi
, then the answer is -1
.
Return an integer array answer
where answer.length == queries.length
and answer[i]
is the answer to the ith
query.
Example 1:
Input: nums = [0,1,2,3,4], queries = [[3,1],[1,3],[5,6]] Output: [3,3,7] Explanation: 1) 0 and 1 are the only two integers not greater than 1. 0 XOR 3 = 3 and 1 XOR 3 = 2. The larger of the two is 3. 2) 1 XOR 2 = 3. 3) 5 XOR 2 = 7.
Example 2:
Input: nums = [5,2,4,6,6,3], queries = [[12,4],[8,1],[6,3]] Output: [15,-1,5]
Constraints:
1 <= nums.length, queries.length <= 105
queries[i].length == 2
0 <= nums[j], xi, mi <= 109
Solutions
Solution 1: Offline Query + Binary Trie
From the problem description, we know that each query is independent and the result of the query is irrelevant to the order of elements in $nums$. Therefore, we consider sorting all queries in ascending order of $m_i$, and also sorting $nums$ in ascending order.
Next, we use a binary trie to maintain the elements in $nums$. We use a pointer $j$ to record the current elements in the trie, initially $j=0$. For each query $[x_i, m_i]$, we continuously insert elements from $nums$ into the trie until $nums[j] > m_i$. At this point, we can query all elements not exceeding $m_i$ in the trie, and we take the XOR value of the element with the maximum XOR value with $x_i$ as the answer.
The time complexity is $O(m \times \log m + n \times (\log n + \log M))$, and the space complexity is $O(n \times \log M)$. Where $m$ and $n$ are the lengths of the arrays $nums$ and $queries$ respectively, and $M$ is the maximum value in the array $nums$. In this problem, $M \le 10^9$.
-
class Trie { private Trie[] children = new Trie[2]; public void insert(int x) { Trie node = this; for (int i = 30; i >= 0; --i) { int v = x >> i & 1; if (node.children[v] == null) { node.children[v] = new Trie(); } node = node.children[v]; } } public int search(int x) { Trie node = this; int ans = 0; for (int i = 30; i >= 0; --i) { int v = x >> i & 1; if (node.children[v ^ 1] != null) { ans |= 1 << i; node = node.children[v ^ 1]; } else if (node.children[v] != null) { node = node.children[v]; } else { return -1; } } return ans; } } class Solution { public int[] maximizeXor(int[] nums, int[][] queries) { Arrays.sort(nums); int n = queries.length; Integer[] idx = new Integer[n]; for (int i = 0; i < n; ++i) { idx[i] = i; } Arrays.sort(idx, (i, j) -> queries[i][1] - queries[j][1]); int[] ans = new int[n]; Trie trie = new Trie(); int j = 0; for (int i : idx) { int x = queries[i][0], m = queries[i][1]; while (j < nums.length && nums[j] <= m) { trie.insert(nums[j++]); } ans[i] = trie.search(x); } return ans; } }
-
class Trie { private: Trie* children[2]; public: Trie() : children{nullptr, nullptr} {} void insert(int x) { Trie* node = this; for (int i = 30; ~i; --i) { int v = (x >> i) & 1; if (!node->children[v]) { node->children[v] = new Trie(); } node = node->children[v]; } } int search(int x) { Trie* node = this; int ans = 0; for (int i = 30; ~i; --i) { int v = (x >> i) & 1; if (node->children[v ^ 1]) { ans |= 1 << i; node = node->children[v ^ 1]; } else if (node->children[v]) { node = node->children[v]; } else { return -1; } } return ans; } }; class Solution { public: vector<int> maximizeXor(vector<int>& nums, vector<vector<int>>& queries) { sort(nums.begin(), nums.end()); int n = queries.size(); vector<int> idx(n); iota(idx.begin(), idx.end(), 0); sort(idx.begin(), idx.end(), [&](int i, int j) { return queries[i][1] < queries[j][1]; }); vector<int> ans(n); Trie trie; int j = 0; for (int i : idx) { int x = queries[i][0], m = queries[i][1]; while (j < nums.size() && nums[j] <= m) { trie.insert(nums[j++]); } ans[i] = trie.search(x); } return ans; } };
-
class Trie: __slots__ = ["children"] def __init__(self): self.children = [None] * 2 def insert(self, x: int): node = self for i in range(30, -1, -1): v = x >> i & 1 if node.children[v] is None: node.children[v] = Trie() node = node.children[v] def search(self, x: int) -> int: node = self ans = 0 for i in range(30, -1, -1): v = x >> i & 1 if node.children[v ^ 1]: ans |= 1 << i node = node.children[v ^ 1] elif node.children[v]: node = node.children[v] else: return -1 return ans class Solution: def maximizeXor(self, nums: List[int], queries: List[List[int]]) -> List[int]: trie = Trie() nums.sort() j, n = 0, len(queries) ans = [-1] * n for i, (x, m) in sorted(zip(range(n), queries), key=lambda x: x[1][1]): while j < len(nums) and nums[j] <= m: trie.insert(nums[j]) j += 1 ans[i] = trie.search(x) return ans
-
type Trie struct { children [2]*Trie } func NewTrie() *Trie { return &Trie{} } func (t *Trie) insert(x int) { node := t for i := 30; i >= 0; i-- { v := x >> i & 1 if node.children[v] == nil { node.children[v] = NewTrie() } node = node.children[v] } } func (t *Trie) search(x int) int { node := t ans := 0 for i := 30; i >= 0; i-- { v := x >> i & 1 if node.children[v^1] != nil { ans |= 1 << i node = node.children[v^1] } else if node.children[v] != nil { node = node.children[v] } else { return -1 } } return ans } func maximizeXor(nums []int, queries [][]int) []int { sort.Ints(nums) n := len(queries) idx := make([]int, n) for i := 0; i < n; i++ { idx[i] = i } sort.Slice(idx, func(i, j int) bool { return queries[idx[i]][1] < queries[idx[j]][1] }) ans := make([]int, n) trie := NewTrie() j := 0 for _, i := range idx { x, m := queries[i][0], queries[i][1] for j < len(nums) && nums[j] <= m { trie.insert(nums[j]) j++ } ans[i] = trie.search(x) } return ans }
-
class Trie { children: (Trie | null)[]; constructor() { this.children = [null, null]; } insert(x: number): void { let node: Trie | null = this; for (let i = 30; ~i; i--) { const v = (x >> i) & 1; if (node.children[v] === null) { node.children[v] = new Trie(); } node = node.children[v] as Trie; } } search(x: number): number { let node: Trie | null = this; let ans = 0; for (let i = 30; ~i; i--) { const v = (x >> i) & 1; if (node.children[v ^ 1] !== null) { ans |= 1 << i; node = node.children[v ^ 1] as Trie; } else if (node.children[v] !== null) { node = node.children[v] as Trie; } else { return -1; } } return ans; } } function maximizeXor(nums: number[], queries: number[][]): number[] { nums.sort((a, b) => a - b); const n = queries.length; const idx = Array.from({ length: n }, (_, i) => i); idx.sort((i, j) => queries[i][1] - queries[j][1]); const ans: number[] = []; const trie = new Trie(); let j = 0; for (const i of idx) { const x = queries[i][0]; const m = queries[i][1]; while (j < nums.length && nums[j] <= m) { trie.insert(nums[j++]); } ans[i] = trie.search(x); } return ans; }