leetcode题解Java | 421. Maximum XOR of Two Numbers in an Array

来源:互联网 发布:怎么入侵网站数据库 编辑:程序博客网 时间:2024/05/17 03:07

题目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 ≤ ij < n.

Could you do this in O(n) runtime?

Example:

Input: [3, 10, 5, 25, 2, 8]Output: 28Explanation: The maximum result is 5 ^ 25 = 28.
分析

这道题有两种思路

解法一:不用trie

利用XOR的性质,a^b = c, 则有 a^c = b,且 b^c = a;
所以每次从高位开始,到某一位为止,所能获得的最大的数为mask(如从1000->1100->1110->1111)。每一次将mask和其他的num相与得到的值加入set,表示从最高位到当前这一位上,数组里有这么多prefix(如当mask为1110,set中最多可能出现以下的数1110,1100,1000,1010)


假定在某一位上的任意两数xor能得到的最大值是tmp,那么他一定满足a(xor)b = tmp,其中set.contains(a) && set.contains(b). 所以,我们只需要判断b(xor)tmp的结果是不是在当前这一位下的set内,就可以知道这个tmp能不能又这个set中的任意两个数组成。

Java实现

public int findMaximumXOR(int[] nums) {        int max = 0, mask = 0;        // test each bit pose, 判断能不能构成所需要的值;        for(int i = 31; i >= 0; i --) {            // 每次都在之前的基础上更新mask            mask = mask | (1 << i);            Set<Integer> set = new HashSet<>();            for(int num : nums) {                // add the number which has the mask as its prefix;                set.add(num & mask);            }            // 假设当前所能达到的最大值是这个temp值;            int tmp = max | (1 << i);            for(Integer prefix : set) {                if(set.contains(prefix ^ tmp)) {                    // 如果能组成就直接break                     max = tmp;                    break;                }            }        }        return max;    }

解法二:用trie

先用nums建一颗二叉树,Trie树的高度为32,建立Trie树的时间复杂度是O(32n)。然后对于每个数,查找它的最大异或值,查找时间是O(32)。所以整体的查找时间复杂度是O(32n),合起来是O(64n)。


一个剪枝。其实在这个算法中,显然有很多重复计算的部分,假设ai的最大异或值是 ai xor aj,那么aj的最大值肯定也是 aj xor ai,这里就是重复计算。因此,我决定改成在建立Trie树的同时,对于正在插入的数,在已插入的数中查找能得到的最大异或值,即边建Trie边查找最大值,这样做也能得到正确的最大异或值。


时间复杂度会高于解法一。代码略。可参考http://www.cnblogs.com/njufl/p/6403043.html


0 0
原创粉丝点击