Maximum XOR of Two Numbers in an Array
Given a non-empty array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 231.
Find the maximum result of ai XOR aj, where 0 ≤ i, j < n.
Could you do this in O(n) runtime?
Example:
Input: [3, 10, 5, 25, 2, 8] Output: 28 Explanation: The maximum result is 5 ^ 25 = 28.
解法1:Trie树。
1. 将所有的数字按bit从高到低建树。
2. 将所有的数字在Trie上进行查询,每当可以有bit相异,则该数字可产生的最大XOR rst <<= 1 且 rst |= 1。
struct TrieNode{
TrieNode* next[2];
TrieNode() {
memset(next, NULL, sizeof(next));
}
};
TrieNode* buildTree(vector<int>& nums){
TrieNode* root = new TrieNode();
TrieNode* p;
for (int num : nums){
p = root;
for (int i = 31; i >= 0; i--){
int index = num >> i & 1;
if (p -> next[index] == NULL){
p = p -> next[index] = new TrieNode();
}
else p = p -> next[index];
}
}
return root;
}
int findMax(TrieNode* root, int num){
int rst = 0;
TrieNode* p = root;
for (int i = 31; i >= 0; i--){
int index = num >> i & 1 ? 0 : 1; //取与该数字bit位相异的index
rst <<= 1;
if (p -> next[index] != NULL){
rst |= 1; //将新增加的低位置1
p = p -> next[index];
}
else p = p -> next[1-index];
}
return rst;
}
int findMaximumXOR(vector<int>& nums) {
TrieNode* root = buildTree(nums);
int maxRst = 0;
for (int num : nums){
maxRst = max(maxRst, findMax(root, num));
}
return maxRst;
}
解法2:每次迭代确定最后的结果一个bit。
int findMaximumXOR(vector<int>& nums) {
int max = 0, mask = 0;
unordered_set<int> t;
// search from left to right, find out for each bit is there
// two numbers that has different value
for (int i = 31; i >= 0; i--){
// mask contains the bits considered so far
mask |= (1 << i);
t.clear();
// store prefix of all number with right i bits discarded
for (int n: nums){
t.insert(mask & n);
}
// now find out if there are two prefix with different i-th bit
// if there is, the new max should be current max with one 1 bit at i-th position, which is candidate
// and the two prefix, say A and B, satisfies:
// A ^ B = candidate
// so we also have A ^ candidate = B or B ^ candidate = A
// thus we can use this method to find out if such A and B exists in the set
// the final result must be obtained by prefix in the set.
int candidate = max | (1<<i);
for (int prefix : t){
if (t.find(prefix ^ candidate) != t.end()){
max = candidate;
break;
}
}
}
return max;
}