Maximum XOR of Two Numbers in an Array

https://leetcode.com/problems/maximum-xor-of-two-numbers-in-an-array/description/

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.

Example:

Input: [3, 10, 5, 25, 2, 8]

Output: 28

Explanation: The maximum result is 5 ^ 25 = 28.

Thoughts

https://leetcode.com/problems/maximum-xor-of-two-numbers-in-an-array/discuss/

想让一个二进制数尽量大, 那么应从高位起尽量让它们为1. 并且当高位为1时, 即使低位为0, 也比低位为1的高位为0的大. 因此我们依次从高位到低位遍历, 判断该位是否能为1, 并且利用之前高位中找出的候选者不断筛选. 比如 [110011, 110010, 010111], 当遍历到第二位时, 即使110011第二位为0, 010111第二位为1, 后者也不用再考虑了. 于是我们可以设置一个candidate表示遍历到i位时, 理想中能达到的最大的数: candidate前i - 1位为前i - 1位中能达到的数, 第i位理想情况下是1. 所以任务变为判断是否有两个数到i位时的prefix相xor能成为candidate. 这时利用xor的性质, 即当a ^ b = candidate时, 有a ^ candidate = b 且 b ^ candidate = a.

Code

class Solution {
    public int findMaximumXOR(int[] nums) {
        int max = 0, mask = 0;
        // search from left to right, find out for each bit is there 
        // two numbers that has different value
        for (int i = 31; i >= 0; i--) {
            // the mask woule be 1000..., 11000..., 111000...
            mask |= (1 << i);
            //System.out.println(Integer.toBinaryString(mask));
            Set<Integer> set = new HashSet<>();
            for (int num : nums) {
                // store prefix of all number with right i bits discarded
                set.add(num & mask);
                //System.out.println(num + "," + Integer.toBinaryString(num) + ": " + Integer.toBinaryString(mask) + "," + Integer.toBinaryString(mask & num));
            }
            // now find out if there are two prefix with different i-th bit
            // if there is, the new max should be current max with one 1 bit at i-th position, which is candidate
            // and the two prefix, say A and B, satisfies:
            // A ^ B = candidate
            // so we also have A ^ candidate = B or B ^ candidate = A
            // thus we can use this method to find out if such A and B exists in the set 
            int candidate = max | (1 << i);
            for (int prefix : set) {
                if (set.contains(candidate ^ prefix)) {
                    max = candidate;
                    break;
                }
            }
        }

        return max;
    }
}

Analysis

时间复杂度O(N).

Last updated