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.
也是看了提示后才知道使用字典树来解决此题。
这里用二叉树来表示trie(网上有用数组来建字典树的,但没看懂),先把nums中的所有数插入到trie中,也就是建树的过程。一个nums[i]插入树中的时间为O(31),n个数的时间复杂度就为O(31n)。然后对于每个nums[i],在树中搜索与其异或值最大的那个nums[j]。过程如下:假设只有三位,比如要搜索的nums[0]==4==100,那么我们在搜索的时候就按011来搜,因为100^011最大。当然如果树中没有011,假如只有001,那么在搜到第二位时,没有1分支只有0分支,那么就只能走0分支了。搜索的时间复杂度也为O(31n)。
总的时间复杂度大概O(62n)。
代码如下:
class Solution {
public:
struct Trie{
Trie* child[2] = {NULL}; //child[0]左子树,代表0,child[1]右子树,代表1。
};
int findMaximumXOR(vector<int>& nums) {
Trie* trie = new Trie;
int i, temp, maxXor = INT_MIN, size = nums.size();
//先建立字典树trie---O(32n)
for(i = 0; i < size; ++i)
insert(trie, nums[i]);
//遍历nums,对于每一个nums[i],都在trie中搜索与nums[i]异或结果最大的那个nums[j].搜索规则是按位取反搜索,即按相反的分支搜。O(32n)
for(i = 0; i < size; ++i){
temp = nums[i]^search(trie, nums[i]);
if(maxXor < temp) maxXor = temp;
}
return maxXor;
}
void insert(Trie* trie, int n){
char bit;
Trie* curNode = trie, *newNode;
for(int i = 30; i >= 0; --i){
bit = (n>>i)&1;
if(curNode->child[bit]==NULL){
newNode = new Trie;
curNode->child[bit] = newNode;
}
curNode = curNode->child[bit];
}
}
int search(Trie* trie, int n){ //返回数组nums中与n相异或结果最大的那个nums[j]
char bit;
int val = 0, POW = pow(2,30);
Trie* curNode = trie;
for(int i = 30; i >= 0; --i){
bit = (n>>i)&1;
if(curNode->child[1-bit]!=NULL){
val += (1-bit)*POW;
curNode = curNode->child[1-bit];
}
else{
val += bit*POW;
curNode = curNode->child[bit];
}
POW /= 2;
}
return val;
}
};