- Maximum XOR of Two Numbers in an Array
Given an integer array nums, return the maximum result of nums[i] XOR nums[j], where 0 ≤ i ≤ j < n.
Follow up: Could you do this in O(n) runtime?
Example 1:
Input: nums = [3,10,5,25,2,8]
Output: 28
Explanation: The maximum result is 5 XOR 25 = 28.
Constraints:
1 <= nums.length <= 2 * 104
0 <= nums[i] <= 231 - 1
这道题难住我了,完全没有思路。看了题目标签有trie,依旧没有思路。看官方题解第一遍看不懂。
反思一下,对于树(包括前缀树)很陌生,位运算很陌生,贪心算法也很陌生,需要练习这三类题。
1.哈希表
数值最大是231-1,即二进制共31位,高位到低位依次编号为30~0
令结果为x,对于结果的每一位,从高到低依次判断是否能为1(此处有贪心思想)。如果已经判定了k-1位,首先假设k位可以为1,则x_next=(x>>1)+1, 由x(k)=nums[i](k) ^ nums[j](k)==> nums[j](k) =nums[i](k) ^ x(k) ,可知,如果此时的x_next满足要求,则一定存在一个数,前k位和x_next异或,结果也是nums的某一个数的前k位。实现这部分的方式是,使用集合存储nums数组中每个数的前k位,然后依次枚举nums中的每个数,判断num^x_next是否在集合中,如果在,说明第k位可以是1,否则第k位是0.
最后返回x
int findMaximumXOR(vector<int>& nums) {
if(nums.size()==1){
return 0;
}
int x=0;
for(int k=30;k>=0;k--){
unordered_set<int>pre;
bool found=false;
for(auto num:nums){
pre.insert(num>>k);
}
int x_next=(x<<1)+1;
for(auto num:nums){
if(pre.count((num>>k)^(x_next))){
found=true;
break;
}
}
if(!found){
x_next-=1;
}
x=x_next;
}
return x;
}
2.前缀树
使用前缀树保存nums中的每一个数据,对于nums[i],前i-1个数已经存储在前缀树中。从根节点向下遍历前缀树。由0^1=1,如果num第k位是0,要想x尽可能大,应该选择第k+1层的右节点;如果num第k位是1,应该选择第k+1层的左节点,
细节:取第k位时,num>>k之后,要&1
前缀树中,root节点以下共31层数值节点,k==30时,cur=root。对于k,cur指向第k+1层
struct Trie{
Trie *left=nullptr;
Trie *right=nullptr;
Trie(){};
};
class Solution {
private:
Trie *root=new Trie();
public:
void add(int num){
Trie *cur=root;
for(int k=30;k>=0;k--){
int bit=(num>>k)&1;
if(bit==0){
if(!cur->left){
cur->left=new Trie();
}
cur=cur->left;
}else{
if(!cur->right){
cur->right=new Trie();
}
cur=cur->right;
}
}
}
int check(int num){
int x=0;
Trie *cur=root;
for(int k=30;k>=0;k--){
int bit=(num>>k)&1;
int x_next=x<<1;
if(bit==0){
if(cur->right){
x_next+=1;
cur=cur->right;
}else{
cur=cur->left;
}
}else{
if(cur->left){
x_next+=1;
cur=cur->left;
}else{
cur=cur->right;
}
}
x=x_next;
}
return x;
}
int findMaximumXOR(vector<int>& nums) {
int x=0;
for(int i=1;i<nums.size();i++){
add(nums[i-1]);
x=max(x,check(nums[i]));
}
return x;
}
};