Maximum XOR of Two Numbers in an Array Problem


Description

LeetCode Problem 421. Given an integer array nums, return the maximum result of nums[i] XOR nums[j], where 0 ≤ i ≤ j < n.

Example:

1
2
3
Input: nums = [3,10,5,25,2,8]
Output: 28
Explanation: The maximum result is 5 XOR 25 = 28.


Solution

Trie and Greedy Approach

We can use the trie data structure to store all the numbers in binary format. Then for each number in nums, we search for the number in the trie that will give us the maximum xor result. To obtain the maximum xor result, we need to find a number in the trie whose binary digits differ most from the number we are checking.

To build the trie, please refer to the Implement Trie Problem post. As we only storing the binary format of the numbers, we only need an array for two elements (0 and 1) in each TrieNode. To make the comparison between number easier, we store all the 32 binary bits for each number.

Then for each number in nums, we search for the number in the trie that will give us the maximum xor result. We iterate through all the 32 bits. The strategy is to choose the oposite bit at each step whenever it is possible. So for any one bit in the number, if the opposite bit (1 to 0, or 0 to 1) exists in the trie, we update the TrieNode with the TrieNode stored in that opposite bit. If the opposite bit does not exist, we then use the TrieNode in the same bit. This is a greedy algorithm to find the number stored in the trie that has maximum digit differences from the number we are checking.


Sample C++ Code

This is a C++ implementation of the trie and greedy approach.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct TrieNode {
    TrieNode* arr[2];
    bool is_end;
    TrieNode() {
        arr[0] = arr[1] = NULL;
        is_end = false;
    }
};

void insert(TrieNode* root, int num) {
    TrieNode* curr = root;
    for (int i = 31; i >= 0; i --) {
        int idx = ((num >> i) & 1);
        if (curr->arr[idx] == NULL)
            curr->arr[idx] = new TrieNode();
        curr = curr->arr[idx];
    }
    curr->is_end = true;
}

int maxXor = 0;

void search(TrieNode* root, int num) {
    TrieNode* curr = root;
    int val = 0;
    for (int i = 31; i >= 0; i --) {
        int idx = ((num >> i) & 1);
        if (idx == 0) {
            if (curr->arr[1] != NULL) {
                curr = curr->arr[1];
                val += (1 << i);
            } else {
                curr = curr->arr[0];
            }
        } else {
            if (curr->arr[0] != NULL) {
                curr = curr->arr[0];
                val += (1 << i);
            } else {
                curr = curr->arr[1];
            }
        }
    }
    if (val > maxXor)
        maxXor = val;
}

int findMaximumXOR(vector<int>& nums) {
    TrieNode* root = new TrieNode();
    for (int i = 0; i < nums.size(); i ++) {
        insert(root, nums[i]);
    }
    for (int i = 0; i < nums.size(); i ++) {
        search(root, nums[i]);
    }
    return maxXor;
}

int main() {
    vector<int> nums = {3,10,5,25,2,8};

    cout << findMaximumXOR(nums) << endl;
}




Related Posts

Map Sum Pairs Problem

LeetCode 677. Design a map that allows you to do...

Palindrome Pairs Problem

LeetCode 336. Given a list of unique words, return all...

Design Add And Search Words Data Structure Problem

LeetCode 211. Design a data structure that supports adding new...

Word Break Problem

LeetCode 139. Given a string s and a dictionary of...

Word Break II Problem

LeetCode 140. Given a string s and a dictionary of...

Stream of Characters Problem

LeetCode 1032. Implement the StreamChecker class as follows. Constructor, initialize...