Maximum XOR of Two Numbers in an Array

update Jul,30 2017 16:25

leetcode

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.

Basic Idea:

这道题用两层for循环可以轻易解决,但是需要O(n^2)的时间复杂度,因为对于每个数,我们需要对比 n 次xor 和 maxXor。于是我们想到,如果可以将求每个数与其他数之间的最大 xor 的过程优化到O(const),我们就可以得到O(const * n)的最终复杂度。因为每个数的长度都相等 (32bit integer),我们就想到可以使用 Trie 来解决。Trie 的高度是32,每层最多有 2 个 node (0 and 1)。则对每个数求其于其他数最大xor的时间是 O(32),共有 n 个数,加上构造 trie 的 O(32n),总的时间为O(2 * 32 n)

Java Code:

    // O(32n) solution using Trie
    public class Solution {
        // define Trie node
        private class TrieNode {
            TrieNode[] child;
            public TrieNode() {
                this.child = new TrieNode[2];
            }
        }

        public int findMaximumXOR(int[] nums) {
            // init trie
            TrieNode root = initTrie(nums);

            // 对每一个数,在trie中找它对所有数xor的最大值,更新全局最大值,就是解
            int globalMax = Integer.MIN_VALUE;
            for (int num : nums) {
                int max = 0; // 可以 O(32) 的时间找到当前数的 maxXor
                TrieNode currNode = root; // 从最高位开始向下查看
                for (int i = 31; i >= 0; --i) {
                    // 检查 currNode.child,如果有和num该位不同的child,则进入,继续寻找不同,
                    // 若没有,则往下继续寻找不同
                    int digit = (num >>> i) & 1;
                    if (currNode.child[digit ^ 1] != null) { // 取反,只对第一位
                        max |= 1 << i; // equlvalent to : max += 1 << i, 因为 i 不会重复
                        currNode = currNode.child[digit ^ 1];
                    } else {
                        currNode = currNode.child[digit];
                    }
                }
                globalMax = Math.max(globalMax, max);
            }
            return globalMax;
        }

        // insert all numbers in trie as 32bit binary sequence
        // 从高位到低位
        private TrieNode initTrie(int[] nums) {
            TrieNode root = new TrieNode();
            for (int num : nums) {
                // 从高到低位插入
                TrieNode currNode = root;
                for (int i = 31; i >= 0; --i) {
                    int digit = (num >>> i) & 1; // 0 or 1
                    if (currNode.child[digit] == null) {
                        currNode.child[digit] = new TrieNode();
                    }
                    currNode = currNode.child[digit];
                }
            }
            return root;
        }
    }

results matching ""

    No results matching ""