题目原文
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:
| 12
 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 树,代码如下:
| 12
 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 讨论区