剑指offer 专项突破版 67、最大的异或

题目链接

思路
  • 这道题暴力法就是两两异或,时间复杂度是O(n²),但是可以用前缀和来优化~
  • 对于一个数X,如果有两个整数m n ,m和n相比,某高位和x的异或结果是1,那么肯定m^x > n^x,基于此我们可以得知想要异或结果大,最好是高位异或结果是1
  • 所以我们可以建立前缀树,只不过这个时候不是以小写英文字母作为结点,而是以0和1,建立的基础是整数的二进制位数,并且高位先建立,因为我们优先选择高位不同的
  • 所以我们首先利用nums数组建立前缀树,这个过程是O(n)
  • 然后再次遍历nums数组,每个num都通过前缀树选择异或最大值,具体选择方法为,如果某一位是x,优先判断前缀树当前节点是否存在和x异或位1的子结点,如果有就选择他,如果没有就选择x
class Solution {
    class TrieNode {
        TrieNode[] children;

        TrieNode() {
            children = new TrieNode[2];
        }
    }

    private TrieNode root;
    int max;

    void buildTree(int[] nums) {
        root = new TrieNode();

        for (int num : nums) {
            TrieNode cur = root;
            for (int i = 31; i >= 0; i--) {
                int bit = num >> i & 1;
                if (null == cur.children[bit])
                    cur.children[bit] = new TrieNode();
                cur = cur.children[bit];
            }
        }
    }

    public int findMaximumXOR(int[] nums) {
        buildTree(nums);

        for (int num : nums) {
            int xor = 0;
            TrieNode cur = root;

            for (int i = 31; i >= 0; i--) {
                xor <<= 1;
                int bit = num >> i & 1;
                if (null != cur.children[1 - bit]) {
                    xor += 1;
                    cur = cur.children[1 - bit];
                }else
                    cur = cur.children[bit];
            }
            max = Math.max(xor,max);
        }
        return max;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值