1. 题目来源
相关题目:
2. 题目解析
没啥难度,整体思想和 [Trie] lc421. 数组中两个数的最大异或值(Trie+Trie的不同写法+算法对比) 一样,加了离线处理罢了。
trie
的经典应用,用来解决最大异或值问题。这里需要根据查询顺序返回答案,很明显的离线处理,但是我一开始使用 pair<vector<int>, int>
维护查询数组和下标时,TLE
了,进而修改为静态结构体解决了。1e5
的数据也能 TLE
,是真的服…
整体思路都一样,没啥好讲的,模板题。
时间复杂度:
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
空间复杂度:
O
(
n
∗
32
)
O(n*32)
O(n∗32)
代码:
const int N = 1e5+5;
int s[N * 32][2], idx;
struct Node {
int x, m, idx;
bool operator<(const Node M) const {
return m < M.m;
}
} Q[N];
class Solution {
public:
void insert(int x) {
int p = 0;
for (int i = 31; ~i; i -- ) {
int u = x >> i & 1;
if (!s[p][u]) s[p][u] = ++ idx;
p = s[p][u];
}
}
int query(int x) {
int res = 0, p = 0;
for (int i= 31; ~i; i -- ) {
int u = x >> i & 1;
if (s[p][!u]) res = res * 2 + !u, p = s[p][!u];
else res = res * 2 + u, p = s[p][u];
}
return res ^ x;
}
// 注意:更加直观,这里的 res=res*2+1等价于 res=res*2+!u
// 因为 u^!u=1,故最终的答案不需要再与 x 异或了,相当于每一位都已经异或了
// res=res*2+!u 是搞出来了 trie 中与 x 最相反的数是多少,
// 其存在于 trie 中, 在 trie 中具备实际意义!
// 而 res=res*2+1 是直接搞出来 trie 中与 x 相反数的异或值,其不一定存在于 trie 中
// 在 trie 中不具备实际意义!
// 理解要透彻
int query(int x) {
int res = 0, p = 0;
for (int i= 31; ~i; i -- ) {
int u = x >> i & 1;
if (s[p][!u]) res = res * 2 + 1, p = s[p][!u];
else res = res * 2, p = s[p][u];
}
return res;
}
vector<int> maximizeXor(vector<int>& nums, vector<vector<int>>& queries) {
memset(s, 0, sizeof s), idx = 0;
int n = queries.size();
for (int i = 0; i < n; i ++ ) Q[i] = {queries[i][0], queries[i][1], i};
sort(nums.begin(), nums.end());
sort(Q, Q + n);
vector<int> res(n);
for (int i = 0, j = 0; i < n; i ++ ) {
int x = Q[i].x, m = Q[i].m, idx = Q[i].idx;
while (j < nums.size() && nums[j] <= m) insert(nums[j ++ ]);
if (!j) res[idx] = -1;
else res[idx] = query(x);
}
return res;
}
};
TLE
代码:
const int N = 1e5+5;
int s[N * 32][2], idx;
class Solution {
public:
void insert(int x) {
int p = 0;
for (int i = 31; ~i; i -- ) {
int u = x >> i & 1;
if (!s[p][u]) s[p][u] = ++ idx;
p = s[p][u];
}
}
int query(int x) {
int res = 0, p = 0;
for (int i= 31; ~i; i -- ) {
int u = x >> i & 1;
if (s[p][!u]) res = res * 2 + !u, p = s[p][!u];
else res = res * 2 + u, p = s[p][u];
}
return res ^ x;
}
vector<int> maximizeXor(vector<int>& nums, vector<vector<int>>& queries) {
memset(s, 0, sizeof s), idx = 0;
int n = queries.size();
vector<pair<vector<int>, int>> Q;
int cnt = 0;
for (auto e : queries) Q.push_back({e, cnt ++ });
sort(nums.begin(), nums.end());
sort(Q.begin(), Q.end(), [](pair<vector<int>, int> a, pair<vector<int>, int> b) {
return a.first[1] < b.first[1];
});
vector<int> res(n);
for (int i = 0, j = 0; i < n; i ++ ) {
int x = Q[i].first[0], m = Q[i].first[1], idx = Q[i].second;
while (j < nums.size() && nums[j] <= m) insert(nums[j ++ ]);
if (!j) res[idx] = -1;
else res[idx] = query(x);
}
return res;
}
};