贪心规律:二进制下,我们希望一个数尽可能大,即希望越高位上越能够出现“1”,这样这个数就是所求的最大数,这是贪心算法的思想。即我们选择的两个数异或要尽可能让高位为1。
方法一:建立一个深度为32的树,从一个数的第31位开始,如果为0则向左子树走,否则向右子树走。最后将数放在叶节点中。在查找时,根据当前的数字,选择和其搭配使异或值最大的数字。即如果该数的某位为1,则需要选择另一个数该位为0,否则只能选1.
int result = 0;
int mask = 0x0;
set<int> num_set;
for(int i = 31; i >=0; i--){
mask = mask | (0x1 << i);
for(auto num:nums){
num_set.insert(num& mask); //将能使第i位变为1的数x(x^num = mask)放入哈希表中
}
//先假设该位为1
int tem = result | (0x1 << i);
for(set<int>::iterator it = num_set.begin(); it != num_set.end(); it++){
if(num_set.find(*it ^ tem) != num_set.end()){ //找到这样的数
result = tem;
break;
}
}
num_set.clear();
}
return result;
方法二:用字典的解法,必须要理解下面的公式:
我们利用贪心算法思想,假设我们最大值的尽可能多的高位为1。先假设最大值高位为1,然后取出vector中数据的高位(即屏蔽低位后放入set中),如果有1^0这种组合,即可说明该位可以为1。然后看结果的次高位是否能为1。屏蔽vector中的数据的除高2位的位数,加入set中。然后在set中寻找是否有这样的组合使高位和次高位都为1.如果没有,说明次高位只能是0。寻找组合的过程,需要用到开头说的公式,就是当前数异或上待定最大值应该为我们查找的能形成最大值组合的那个数。
struct TreeNode{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int _val): val(_val), left(nullptr), right(nullptr) {}
};
public:
int findMaximumXOR(vector<int>& nums) {
//字典和建树都需要用到贪心算法
//建树 0->left 1->right
TreeNode root(-1);
int max = 0;
//先进行建树
for(auto num : nums){
TreeNode* ptr = &root;
for(int i = 31; i >= 0; i--){
if(num & (0x1 << i)){
if(ptr->right == nullptr){
ptr->right = new TreeNode(1);
}
ptr = ptr->right;
}else{
if(ptr->left == nullptr){
ptr->left = new TreeNode(0);
}
ptr = ptr->left;
}
}
ptr->left = new TreeNode(num);
}
//应用贪心算法,查找当前num下能产生最大异或值得组合
for(auto num : nums){
TreeNode* ptr = &root;
for(int i = 31; i >=0; i--){
if(num & (0x1 << i)){ //当前位是1,则必须查找该位为0的如果没有就走1的路
if(ptr->left){
ptr = ptr->left;
}else{
ptr = ptr->right;
}
}else{
if(ptr->right){
ptr = ptr->right;
}else{
ptr = ptr->left;
}
}
}
if((num^(ptr->left->val)) > max){
max = (num^(ptr->left->val));
}
}
return max;
}