[AcWing] 143. 最大异或对(C++实现)---trie例题
1. 题目
2. 读题(需要重点注意的东西)
思路:
异或:
如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。(相同为0,不同为1)
如 1(十进制) = 0001(2进制), 2 = 0010, 3 = 0011
1 ⊕ 2 = 0011 = 3, 1 ⊕ 3 = 0010 , 2 ⊕ 3 = 0001 —> 异或得到最大值为 3
解题过程:
① 将所有的数建trie
② 然后让每个数走一遍trie(当前位上为0则在trie上走1,当前位上为1则在trie上走0,然后继续看下一位),得到的结果与其进行异或,就是该数的最大异或
③ 对所有数的最大异或取max,即为答案
3. 解法
---------------------------------------------------解法---------------------------------------------------
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010, M = 3100010;
int n;
int a[N], son[M][2], idx;
void insert(int x)
{
int p = 0;
for (int i = 30; i >= 0; i -- ) // i >= 0 等价于 ~i ,因为-1 = 111...1,取反-1就是0
{
int &s = son[p][x >> i & 1];
if (!s) s = ++ idx; // 创建一个新节点
p = s;
}
}
int search(int x)
{
int p = 0, res = 0;
for (int i = 30; i >= 0; i -- )
{
int s = x >> i & 1;
if (son[p][!s]) // 如果有不同当前位上值的分支
{
res += 1 << i;
p = son[p][!s];
}
else p = son[p][s]; // 否则只能走当前位上的分支
}
return res;
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i ++ )
{
scanf("%d", &a[i]);
insert(a[i]); // 将每个数插入trie树中
}
int res = 0;
for (int i = 0; i < n; i ++ ) res = max(res, search(a[i])); // 求出每个数的最大异或值,再求max
printf("%d\n", res);
return 0;
}
可能存在的问题(所有问题的位置都在上述代码中标注了出来)
4. 可能有帮助的前置习题
5. 所用到的数据结构与算法思想
- Trie 前缀树
6. 总结
Trie 前缀树的例题,理解思想并实现代码。