421. 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.

这道题是一道典型的位操作Bit Manipulation的题目,我开始以为异或值最大的两个数一定包括数组的最大值,但是OJ给了另一个例子{10,23,20,18,28},这个数组的异或最大值是10和20异或,得到30。那么只能另辟蹊径,正确的做法是按位遍历,题目中给定了数字的返回不会超过231,那么最多只能有32位,我们用一个从左往右的mask,用来提取数字的前缀,然后将其都存入set中,我们用一个变量t,用来验证当前位为1再或上之前结果res,看结果和set中的前缀异或之后在不在set中,这里用到了一个性质,若a^b=c,那么a=b^c,因为t是我们要验证的当前最大值,所以我们遍历set中的数时,和t异或后的结果仍在set中,说明两个前缀可以异或出t的值,所以我们更新res为t,继续遍历,如果上述讲解不容易理解,那么建议自己带个例子一步一步试试,并把每次循环中set中所有的数字都打印出来,基本应该就能理解了,参见代码如下:

public class Solution {
    public int findMaximumXOR(int[] nums) {
        int mask = 0, max = 0;
        for (int i=31; i>=0; i--) {
            mask |= 1<<i;
            HashSet<Integer> prefixes = new HashSet<Integer>();
            for (int each : nums) {
                prefixes.add(each & mask); // reserve Left bits and ignore Right bits
            }
            int tmpMax = max | (1<<i);   
            //possible new max, for example: max right now is 11000, then tmpMax=11100, max is 11100, tmpMax is 11110
            for (int prefix : prefixes) {
                if (prefixes.contains(tmpMax^prefix)) 
                    max = tmpMax;
            }
        }
        return max;
    }
}

  

Solution 2: Trie, (未研究)

https://discuss.leetcode.com/topic/63207/java-o-n-solution-using-trie

https://discuss.leetcode.com/topic/64753/31ms-o-n-java-solution-using-trie

 
posted @ 2017-07-15 22:12  apanda009  阅读(114)  评论(0编辑  收藏  举报