题目原文
Difficulty: Medium
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:
1 2 3 4 5
| Input: [3, 10, 5, 25, 2, 8]
Output: 28
Explanation: The maximum result is 5 ^ 25 = 28.
|
解法:使用 Trie 树(前缀树)和分治法
时间复杂度 O(n)
根据题目描述,我们需要找到最大的异或值,异或代表了两个数的二进制的不同程度,且越高位越不一样,异或值就越大,由于是按位比较,所以使用 Trie 树来当做基础数据结构。
我们可以总结出以下几点:
- 因为整型的位数是固定的,排除第一位符号位,Trie 树的高度是常数的,即最高
32
层(包括root
)
- 由于只有
0
和1
两个子节点,所以为了节省空间,可以使用二叉树
的方式(或者数组和 HashMap 均可)
- 由于是异或,前缀位如果相同,异或值都是 0,所以可以先找到第一个两个子节点都不为空的节点当做
root
以此构建 Trie 树,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| class Solution { class TrieNode { int val; TrieNode zero, one; boolean isEnd; } class TrieTree { TrieNode root; public TrieTree() { root = new TrieNode(); } public void insert(int num) { TrieNode cur = root; int j = 1 << 30; for (int i = 0; i < 31; i++) { int b = (j & num) == 0 ? 0 : 1; if (b == 0 && cur.zero == null) { cur.zero = new TrieNode(); } if (b == 1 && cur.one == null) { cur.one = new TrieNode(); } cur = b == 0 ? cur.zero : cur.one; j >>= 1; } cur.isEnd = true; cur.val = num; } }
public int findMaximumXOR(int[] nums) { if (nums == null || nums.length <= 1) { return 0; } TrieTree tree = new TrieTree(); for (int n : nums) { tree.insert(n); } TrieNode cur = tree.root; while (cur.one == null || cur.zero == null) { cur = cur.zero != null ? cur.zero : cur.one; } return maxHelper(cur.one, cur.zero);
}
private int maxHelper(TrieNode one, TrieNode zero) { if (one.isEnd && zero.isEnd) { return one.val ^ zero.val; } if (one.zero == null) { return maxHelper(one.one, zero.zero == null ? zero.one : zero.zero); } else if (one.one == null) { return maxHelper(one.zero, zero.one == null ? zero.zero : zero.one); } else if (zero.zero == null) { return maxHelper(one.zero, zero.one); } else if (zero.one == null) { return maxHelper(one.one, zero.zero); } else { return Math.max(maxHelper(one.one, zero.zero), maxHelper(one.zero, zero.one)); } } }
|
本文同样发在了 LeetCode 讨论区