最大异或对
题目链接
在给定的N个整数A1,A2……AN中选出两个进行xor(异或)运算,得到的结果最大是多少?
输入格式
第一行输入一个整数N。
第二行输入N个整数A1~AN。
输出格式
输出一个整数表示答案。
数据范围
1≤N≤105,
0≤Ai<231.
输入样例:
3
1 2 3
输出样例:
3
算法分析
这题如果要暴力的话就是 至少O(n2) 最多O(31n2)那肯定是不行的,那么就要进行优化,遍历数是无法避免的.而异或是可以进行位运算的,所以我们以位运算来进行优化,要是异或和大,那么位不同的数越多越好.每一位我们用二进制表示,那么就可以转换为字典树的形式,来遍历,这样我们的时间复杂度就可以降到O(31n).
代码实现
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<math.h>
using namespace std;
const int maxn=1e5+5;
int n,a[maxn];
int son[maxn*31][2],idx;
//son[p][u] p代表当前所在树枝,u代表当前所在结点是1还是0;
void insert(int x)
{
int p=0;
for(int i=30;i>=0;i--)//从最高位30位进行遍历
{
int u=x>>i&1;//当前位数为1的话就是1.
if(!son[p][u])//如果不存在当前节点,就建立
son[p][u]=++idx;
p=son[p][u];//更新树枝,往下遍历
}
}
int quary(int x)
{
int res=0; //代表和
int p=0;
for(int i=30;i>=0;i--)//从高位遍历
{
int u=x>>i&1; //当前位数为1的话就是1.
if(son[p][!u])//如果有和当前位不同的分支,我们就走该分支保证异或最大.
{
p=son[p][!u];//更新分支
res+=1<<i;//加上当前位所代表的数量(因为只要不相同就是1,不用管数是谁)
}
else //没有不同的结点就继续往下遍历
p=son[p][u];
}
return res;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
insert(a[i]);
}
int res=0;
for(int i=1;i<=n;i++)//寻找最大值
{
res=max(res,quary(a[i]));
}
cout<<res<<endl;
}