Maximum XOR of Two Numbers in an Array

60 篇文章 1 订阅
  1. Maximum XOR of Two Numbers in an Array

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.

我的代码

class Solution {

	public int findMaximumXOR(int[] nums) {
		if (nums.length == 0) {
			return 0;
		}

		TrieNode root = new TrieNode();

		// 建树
		// 每一个数字循环32次,反正输入没有负数
		// 从最高位开始处理
		for (int i : nums) {
			TrieNode node = root;
			for (int j = 31; j >= 0; j--) {
				int bit = (i >> j) & 1;
				if (bit == 1) {
					if (node.one == null) {// one的位置是null,就新建
						node.one = new TrieNode();
					}
					node = node.one;
				} else {
					if (node.zero == null) {
						node.zero = new TrieNode();
					}
					node = node.zero;
				}
			}
		}

		int max = Integer.MIN_VALUE;

		//找每一个数字和别的数字异或出来的最大值!
		//所有最大值,取其中最大的
		for (int i : nums) {
			TrieNode node = root;
			int XOR = 0;// 异或结果,的累加。按位累加也是牛逼
			for (int j = 31; j >= 0; j--) {
				int bit = (i >> j) & 1;
				//如果这一位是1,为了异或最大,最好使用0,这样异或出来是1
				//如果0不存在就只能使用1,这样这一位异或出来就是0
				//如果这一位是0,为了异或最大,最好使用1,这样异或出来是1
				//如果1不存在就只能使用0,这样这一位异或出来就是0
				if (bit == 1) {
					if (node.zero != null) {
						node = node.zero;
						XOR += 1 << j;
					} else {
						node = node.one;
						XOR += 0 << j;// 0没用为了明确还是写上
					}
				} else {
					if (node.one != null) {
						node = node.one;
						XOR += 1 << j;
					} else {
						node = node.zero;
						XOR += 0 << j;
					}
				}
			}
			max = max > XOR ? max : XOR;
		}

		return max;
	}
}

class TrieNode {
	TrieNode zero;
	TrieNode one;
}

同样思路
trick: 通过预处理得到最大值的首位1,优化了Trie树的深度。

class Solution {
   
    TreeNode root = new TreeNode(0);

    public int findMaximumXOR(int[] nums) {
        int max = findMax(nums);
        int maxBit = 32 - Integer.numberOfLeadingZeros(max);
        //build prefix tree
        TreeNode currNode = root;
        for (int i = 0; i < nums.length; i++) {
            for (int j = maxBit -1; j >=0 ; j--) {
                int tmp = (nums[i] >>j)& 1;
                if(tmp == 0)
                {
                    if(currNode.left == null)
                    {
                        currNode.left = new TreeNode(0);
                    }
                    currNode = currNode.left;
                }else {
                    if(currNode.right == null)
                    {
                        currNode.right = new TreeNode(1);
                    }
                    currNode = currNode.right;
                }
            }
            // finished for nums[i], will do it for nums[i++];
            currNode = root;
        }

        //find max xor value
        int maxXOR = 0;

        for (int i = 0; i < nums.length; i++) {
            int res = 0;
            for (int j = maxBit -1; j >=0; j--) {
                int tmp = (nums[i] >>j)& 1;
                if(currNode.left != null && currNode.right != null)
                {
                    if(tmp == 0)
                    {
                        currNode = currNode.right;
                    }else {
                        currNode = currNode.left;
                    }
                }else {
                    currNode = currNode.left == null ? currNode.right : currNode.left;
                }

                res += (tmp^currNode.val) << j;
            }
            currNode = root;
            maxXOR = maxXOR > res ? maxXOR : res;
        }
        return maxXOR;
    }
    private int findMax(int[] nums)
    {
        int max = nums[0];
        for (int i = 1; i < nums.length; i++) {
            if(nums[i] > max)
            {
                max = nums[i];
            }
        }
        return max;
    }
    private static class TreeNode{
        int val;
        TreeNode left,right;
        TreeNode(int val)
        {
            this.val = val;
        }
    }
}

Bit maniputaipon
这个解法也是利用前缀树的思想,利用Map保存下一次遍历的前缀。(空间换时间)
贪心思想,从最大的bit到最小的bit组装最大异或值。
借用一段解释:
I think most people who find it hard to understand the code is stuck on this line if(set.contains(tmp ^ prefix))
The tricky part here is that we need to be aware of a key property of XOR applying on the above line: if A ^ B = C, then A ^ B ^ B = C ^ B, then A = C ^ B
Before executing that line, max stands for the maximum we can get if we consider only the most significant i - 1 bits, tmp stands for the potential max value we can get when considering the most significant i bits. How can we get this tmp? The only way we can get this value is that we have two values A and B in the set (a set of most significant i bits of each member), such that A ^ B equals to tmp. As mentioned earlier, A ^ B = tmp is equivalent to A = tmp ^ B. Here is where that line comes in: set.contains(tmp ^ B).

public class Solution {
    public int findMaximumXOR(int[] nums) {
        int max = 0, mask = 0;
        for(int i = 31; i >= 0; i--){
            mask = mask | (1 << i);
            Set<Integer> set = new HashSet<>();
            for(int num : nums){
                set.add(num & mask);
            }
            int tmp = max | (1 << i);
            for(int prefix : set){
                if(set.contains(tmp ^ prefix)) {
                    max = tmp;
                    break;
                }
            }
        }
        return max;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值