字典树可以看一下这位大佬的文章:
【数据结构】字典树TrieTree图文详解_Avalon Demerzel的博客-CSDN博客
4、最大异或对
给定N个整数A1、A2、A3……A**N;从中选出两个数进行异或运算,得到结果的最大值是多少?
数据范围:
1≤N≤10^5
1≤A(i)≤10^8;
Input
第一行输入一个数N;
第二行输入N个数表示:A1、A2……A(N)。
Output
输出一个数,表示答案。
Sample Input 1
3 1 2 3
Sample Output 1
3
Source
#include<stdio.h>
#include<assert.h>
#include<malloc.h>
#include<math.h>
#include<string.h>
int son[100010][2] = { 0 };
int idx = 1;
int a[100010] = { 0 };
int max(a, b)
{
if (a > b)
return a;
else
return b;
}
void insert(int x)
{
int p = 0;
int i = 0;
for (i = 30; i >= 0; --i)
{
//取出x的二进制最高位
int u = x >> i & 1;
if (son[p][u] == 0)
{
son[p][u] = idx;
++idx;
}
p = son[p][u];
}
}
//用于找寻某个数在已建字典树中
//对应最大异或数是多少
int find(int x)
{
int p = 0, res = 0;
int i = 0;
for (i = 30; i >= 0; --i)
{
int u = x >> i & 1;
//检查对应层有无不同的数
if (son[p][!u]) //有不同数
{
p = son[p][!u]; //p就指到不同数的地址
//res=res+(1<<i);
//还原某数最大异或数对应二进制数字为十进制
//原理:难以理解┭┮﹏┭┮(原理见下图)
//原理:补充,二进制本质为某个数进行短除法的余数
//而res = (res * 2) + !u是对短除的逆过程
res = (res * 2) + !u;
}
else //没有不同数
{
p = son[p][u];
res = (res * 2) + u;
}
}
return res;
}
int main()
{
int n = 0;
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
int res = 0;
for (int i = 0; i < n; i++)
{
insert(a[i]);
int t = find(a[i]);
res = max(res, a[i] ^ t);
}
printf("%d\n", res);
return 0;
}