字典树 太迷糊了 写写理理思路
题目描述
在给定的 个整数 中选出两个进行异或运算,得到的结果最大是多少?
输入格式
第一行一个整数 。
第二行 个整数 。
输出格式
一个整数表示答案。
我看了别人的题解是这样的“由于只要求在n个数中找到两个数异或的最大值,所以我们目标就是找到两个数,他们的对应二进制位不同的个数最多。所以问题就变成了给定一个数,去寻找另一个和它匹配时异或值最大的数。所以我们可以采用Trie,我们将n个数按照二进制31位插入到字典树中,每次对于一个数x,我们按照其二进制位搜索路径,优先搜索相反位。原文链接:https://blog.csdn.net/weixin_41162823/article/details/89421444”就是说 要把这个数变成二进制形式 加入到字典树中,那这个树就以一串01字符串的形式储存在字典树中了,把所有的树都加入到树中以后,我们挨个找每个树,谁与这个树有最大的不同的位(他是0她是1这样的意思)
代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int ch[4010000][2];
long long a[110010];
int tot;
void insert(int x)
{
int u=0;
for(int i=30; i>=0; i--)
{
int k=(x>>i)&1;
if(!ch[u][k])
ch[u][k]=++tot;
u=ch[u][k];
}
}
long long find(long long x)
{
int p=0;
long long ans=0;
for(int i=30; i>=0; i--)
{
int k=(x>>i)&1;
if(ch[p][!k])//如果在p对应的深度上有!k 就沿着这个路径接着搜索
{
p=ch[p][!k];
ans=(ans<<1)|1;//我不理解
}
else
{
p=ch[p][k];
如果没有也只好继续搜索
ans=(ans<<1);
}
}
return ans;
/*
int p = 1,ans = 0;
for(int k = 30;k >= 0;k--)
{
int ch = x>>k&1;
if(t[p][!ch])
{
ans = ans|(1<<k); 感觉这样写更好理解一点 如果!ch存在 那这个位置异或后的结果就为1 加上这个位置所对应的二进制数
p = t[p][!ch];
}else p = t[p][ch];
} */
}
int main()
{
int i,j,k,m,n;
tot=0;
scanf("%d",&n);
for(i=1; i<=n; i++)
{
scanf("%lld",&a[i]);
insert(a[i]);// 把这个树以01串的形式加入到字典树中
}
long long ans=-1;
for(i=1; i<=n; i++)
{
ans=max(ans,find(a[i]));//寻找a【i】对应的
}
printf("%lld\n",ans);
return 0;
}