题目描述:
解:
421.数组中两个数的最大异或值的进阶版
此题也是求最大的异或值,同样需要构造一个01字典树。有区别的是:
- 采取离线查询的方法:每次将需要参加筛选的值加入到字典树
- 采取在线查询的方法:一次性将数组所有值加入字典树,再对于每一个查询的值进行判断。
以下代码是抄官解的:
1.离线查询:
class Solution {
public int[] maximizeXor(int[] nums, int[][] queries) {
Arrays.sort(nums);
int numQ = queries.length;
int[][] newQueries = new int[numQ][3];
for (int i = 0; i < numQ; ++i) {
newQueries[i][0] = queries[i][0];
newQueries[i][1] = queries[i][1];
newQueries[i][2] = i;
}
Arrays.sort(newQueries, new Comparator<int[]>() {
public int compare(int[] query1, int[] query2) {
return query1[1] - query2[1];
}
});
int[] ans = new int[numQ];
Trie trie = new Trie();
int idx = 0, n = nums.length;
for (int[] query : newQueries) {
int x = query[0], m = query[1], qid = query[2];
while (idx < n && nums[idx] <= m) {
trie.insert(nums[idx]);
++idx;
}
if (idx == 0) { // 字典树为空
ans[qid] = -1;
} else {
ans[qid] = trie.getMaxXor(x);
}
}
return ans;
}
}
class Trie {
static final int L = 30;
Trie[] children = new Trie[2];
public void insert(int val) {
Trie node = this;
for (int i = L - 1; i >= 0; --i) {
int bit = (val >> i) & 1;
if (node.children[bit] == null) {
node.children[bit] = new Trie();
}
node = node.children[bit];
}
}
public int getMaxXor(int val) {
int ans = 0;
Trie node = this;
for (int i = L - 1; i >= 0; --i) {
int bit = (val >> i) & 1;
if (node.children[bit ^ 1] != null) {
ans |= 1 << i;
bit ^= 1;
}
node = node.children[bit];
}
return ans;
}
}
2.在线查询
class Solution {
public int[] maximizeXor(int[] nums, int[][] queries) {
Trie trie = new Trie();
for (int val : nums) {
trie.insert(val);
}
int numQ = queries.length;
int[] ans = new int[numQ];
for (int i = 0; i < numQ; ++i) {
ans[i] = trie.getMaxXorWithLimit(queries[i][0], queries[i][1]);
}
return ans;
}
}
class Trie {
static final int L = 30;
Trie[] children = new Trie[2];
int min = Integer.MAX_VALUE;
public void insert(int val) {
Trie node = this;
node.min = Math.min(node.min, val);
for (int i = L - 1; i >= 0; --i) {
int bit = (val >> i) & 1;
if (node.children[bit] == null) {
node.children[bit] = new Trie();
}
node = node.children[bit];
node.min = Math.min(node.min, val);
}
}
public int getMaxXorWithLimit(int val, int limit) {
Trie node = this;
if (node.min > limit) {
return -1;
}
int ans = 0;
for (int i = L - 1; i >= 0; --i) {
int bit = (val >> i) & 1;
if (node.children[bit ^ 1] != null && node.children[bit ^ 1].min <= limit) {
ans |= 1 << i;
bit ^= 1;
}
node = node.children[bit];
}
return ans;
}
}