In this problem we need to find the maximum XOR between 2 elements of 2 arrays.
Example:
javascriptlet array = [5, 1, 7, 4, 3]; let queries = [2, 0]; /* queries[0] 2 ⊕ 5 = 7 <----- Max XOR 2 ⊕ 1 = 3 2 ⊕ 7 = 5 2 ⊕ 4 = 6 2 ⊕ 3 = 1 */ /* queries[1] 0 ⊕ 5 = 5 0 ⊕ 1 = 1 0 ⊕ 7 = 7 <----- Max XOR 0 ⊕ 4 = 4 0 ⊕ 3 = 3 */ /* res = [7, 7] */
The first approach is to iterate both arrays, calculating the maximum XOR for each pair of elements. The problem of this solution is that it's O(n · m) and not efficient.
The second approach is to notice that:
maxXOR = binary ⊕ inverse
Example:
javascriptlet binary = '101'; // 5 let inverse = '010'; // 2 let maxXor = binary ^ inverse; // 111 -> 7
Given two arrays, array
and queries
:
array
values.queries
and, for each value, find the closest inverse in the tree.maxXor = binary ⊕ closest
At first, we'll create a tree using array
.
Example:
javascriptlet array = [5, 1, 7, 4, 3]; let binary = ['101', '001', '111', '100', '011'];
The tree allows to perform a quick search of the closest inverse values that we are looking for.
terminalroot / \ / \ / \ 0 1 /\ / \ / \ / \ 00 01 10 11 \ \ /\ \ \ \ / \ \ 001 011 100 101 111
Translating it into code:
javascript// Defining empty tree let tree = {}; // Defining empty branch let branch = ''; for(let i = 0; i < array.length; i ++){ // Getting decimal let decimal = array[i]; // Defining a 32-bits empty string let empty = ('0').repeat(32); // Transforming decimal into 32-bits binary let binary = (empty + decimal.toString(2)).slice(-32); // Iterating through 32-bits binary for(let j = 0; j < binary.length; j ++){ // Adding one bit to current branch branch += binary[j]; // Defining branch as empty object tree[branch] = {}; // Adding 0 and 1 to left and right branches if(branch !== binary){ if(binary[j + 1] === '0') tree[branch].left = branch + '0'; if(binary[j + 1] === '1') tree[branch].right = branch + '1'; } } // Resetting branch branch = ''; }
Now, we need to find the closest inverse value for each query.
javascript// Defining closest value let closest = ''; // Defining array of max XOR's let res = []; for(let i = 0; i < queries.length; i ++){ // Getting decimal let decimal = queries[i]; // Defining a 32-bits empty string let empty = ('0').repeat(32); // Transforming decimal into 32-bits binary let binary = (empty + decimal.toString(2)).slice(-32); for(let j = 0; j < binary.length; j ++){ // Getting current bit and inverting it let current = binary[j]; let inverse = binary[j] === '1' ? '0' : '1'; // Update closest value depending on the tree if(tree[closest + inverse]) closest += inverse; else closest += current; } // Defining max // maxXor = binary ⊕ closest` let maxXor = parseInt(binary, 2) ^ parseInt(closest, 2); // Adding to result res.push(maxXor); // Resetting closest value closest = ''; }
And that's it!
Hi, I'm Erik, an engineer from Barcelona. If you like the post or have any comments, say hi.