1707. 与数组中元素的最大异或值
给你一个由非负整数组成的数组 nums 。另有一个查询数组 queries ,其中 queries[i] = [xi, mi] 。
第 i 个查询的答案是 xi 和任何 nums 数组中不超过 mi 的元素按位异或(XOR)得到的最大值。换句话说,答案是 max(nums[j] XOR xi) ,其中所有 j 均满足 nums[j] <= mi 。如果 nums 中的所有元素都大于 mi,最终答案就是 -1 。
返回一个整数数组 answer 作为查询的答案,其中 answer.length == queries.length 且 answer[i] 是第 i 个查询的答案。
示例 1:
输入:nums = [0,1,2,3,4], queries = [[3,1],[1,3],[5,6]]
输出:[3,3,7]
解释:
- 0 和 1 是仅有的两个不超过 1 的整数。0 XOR 3 = 3 而 1 XOR 3 = 2 。二者中的更大值是 3 。
- 1 XOR 2 = 3.
- 5 XOR 2 = 7.
示例 2:
输入:nums = [5,2,4,6,6,3], queries = [[12,4],[8,1],[6,3]]
输出:[15,-1,5]
插入
将nums中的每个数字转换为长度为L的二进制数,根据字典树的插入算法,将该数字插入到字典树中,每个结点都有两个孩子children[2],根据二进制数的0和1,判断是否有孩子。
查询异或最大值
设比较值为25,即11001,从头开始遍历字典树,判断每个结点存在于children的位置,如果在0位置则表示该结点表示二进制中的一位:0,如果在1位置则表示二进制中的一位:1,遍历该字典树,遍历过程中,为寻找最大异或数,每次都要判断与比较值中对应位异或值为1的结点是否存在,由于该树是从二进制高位开始往低位延伸,所以越早遇到与比较值中对应位异或值为1的结点,得出的结果会越大,所以只需要从头开始遍历,遇到这种结点,就可以在结果中将该位记为1,遍历完成,得到最大值。
class Trie {
public:
const int L = 30;
Trie* children[2] = {};
void insert(int val) {
Trie* node = this;
for (int i = L - 1; i >= 0; --i) {
int bit = (val >> i) & 1; //从高位开始插入
if (node->children[bit] == nullptr)
{
node->children[bit] = new Trie();
}
node = node->children[bit];
}
}
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] != nullptr) {
ans |= 1 << i; //保存结果
bit ^= 1; //从与自身异或值为1的结点位置继续往下查询
}
node = node->children[bit];
}
return ans;
}
};
class Solution1707 {
public:
vector<int> maximizeXor(vector<int> &nums, vector<vector<int>> &queries) {
sort(nums.begin(), nums.end());
int numQ = queries.size();
for (int i = 0; i < numQ; ++i)
{
queries[i].push_back(i);
}
// {{12,4,0},{8,1,1},{6,3,2}}
//按照 每个元素中的第二个数的大小排序
sort(queries.begin(), queries.end(), [](auto &x, auto &y) { return x[1] < y[1]; });
//===》 {8,1,1} {6,3,2} {12,4,0} 这样可以保持对应关系 例如寻找与1的异或最大值时,字典树 中的元素都是小于等于1的。
vector<int> ans(numQ);
Trie* t = new Trie();
int idx = 0, n = nums.size();
for (auto &q : queries)
{
//x 8 m 1 qid 1
int x = q[0], m = q[1], qid = q[2];
while (idx < n && nums[idx] <= m) {
t->insert(nums[idx]);
++idx;
}
if (idx == 0) { // 字典树为空
ans[qid] = -1;
} else {
ans[qid] = t->getMaxXor(x);
}
}
return ans;
}
};