【LeetCode】Maximum XOR of Two Numbers in an Array

这个题最开始想到的就是O(N^2)的做法,但是显然不满足要求,后来又从最大最小值入手考虑,但是没发现具体规律。

最后看了后面别人的做法,开始没太看懂,后来花费了点时间才搞懂了。贴上别人的代码和自己的理解

package leetcode;


import java.util.HashSet;
import java.util.Set;


public class MaximumXOR {
//1、利用字典树
class Trie {
       Trie[] children;
       public Trie() {
           children = new Trie[2];
       }
   }
   
   public int findMaximumXOR(int[] nums) {
       if(nums == null || nums.length == 0) {
           return 0;
       }
       // Init Trie.构造字典树
       Trie root = new Trie();
       for(int num: nums) {
           Trie curNode = root;
           for(int i = 31; i >= 0; i --) {
               int curBit = (num >>> i) & 1;
               if(curNode.children[curBit] == null) {
                   curNode.children[curBit] = new Trie();
               }
               curNode = curNode.children[curBit];
           }
       }
       int max = Integer.MIN_VALUE;
       for(int num: nums) {
           Trie curNode = root;
           int curSum = 0;
           for(int i = 31; i >= 0; i --) {
               int curBit = (num >>> i) & 1;
               /*
                * curBit ^ 1 相当于curBit的反码,只有尽可能的匹配数字的反码
                * 得到的结果才是最大的,因为与反码 ^ 得到的结果是1
                */
               if(curNode.children[curBit ^ 1] != null) {
                   curSum += (1 << i);
                   curNode = curNode.children[curBit ^ 1];
               }else {
                   curNode = curNode.children[curBit];
               }
           }
           max = Math.max(curSum, max);
       }
       return max;
   }
   //2、用set集合
   public int findMaximumXOR1(int[] nums) {
       int max = 0;
   
       int mask = 0;
       
       for(int i = 31; i >= 0; i--) {
           mask = mask | (1 << i);//用mask从左到右提取前缀
           /*mask的变化情况
            * 10000000...
            * 11000000...
            * 11100000...
            * 11110000...
            * 11111000...
            * ....
            */
           Set<Integer> set = new HashSet<Integer>();
           for(int num : nums) {
               set.add(num & mask);//将数组中每个数的相应前缀提取出来,放到set里面
           }
           /*
            * res代表当前情况可能的最大值。比如说max是10000...
            * 则res就是11000...,如果后面res可以得到,那就说明res这种情况存在
            * 就是最大值,将其赋给max。
            */
           int res = max | (1 << i);
           for(int premix : set) {
            /*
            * 这里用到一个性质,如果a ^ b = c, 则 a = c ^ b;
            * 如果说res^premix在set集合中,则说明set中有两个数异或可以得到res
            * 将res赋值给max.
            */
               if(set.contains(premix^res)) {
                   max = res;
                   break;
               }
           }
       }
       return max;
   }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值