目录
一:概念定义
异或:两个数字转化为二进制数,从低位开始进行异或运算。异或也算也可称之为不进位加法。这题和上一题字符串统计有异曲同工之妙,两者一起食用效果较好。
二:题目描述
在给定的 N 个整数中选出两个进行 xor(异或)运算,得到的结果最大是多少?
输入格式
第一行输入一个整数 N。
第二行输入 N 个整数 。
输出格式
输出一个整数表示答案
数据范围
1 ≤ N ≤ 10^5,
0 ≤ Ai < 2^31
输入样例
3
1 2 3
输出样例
3
三:思路分析
这题当然有谁都能想到的朴素做法,两层for循环,但是会超时,因此需要改进算法,利用Trie树进行简化。
首先需要搞懂几个目标:
1.数字要大,说明其转化为二进制的1要尽可能多且在最高位是1的情况下位数尽可能多。
2.转化为二进制的最大数字不会超过2^31,因此最多是31位进行存储。
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 --)
{
int u = x >> i & 1;//从高位取数
if (!son[p][u]) son[p][u] = ++idx;//不存在这个节点就创造这个节点
p = son[p][u];//每次都要走到下一个节点
}
}
int search(int x)
{
int p = 0, res = 0;
for (int i = 30; i >= 0; i -- )
{
int u = x >> i & 1;//从高位取数
if (son[p][!u])//如果存在非的数,就往非的方向走
{
res += 1 << i;//将1左移i位
p = son[p][!u];
}
else p = son[p][u];//不存在非的数字,只能顺势而下
}
return res;
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i ++ )
{
scanf("%d", &a[i]);
insert(a[i]);
}
int res = 0;
for (int i = 0; i < n; i ++ ) res = max(res, search(a[i]));
printf("%d\n", res);
return 0;
}
创作不易,建议点赞+收藏+关注,以免找不到宝贝文章了。
基础集训结束后将开展拔高系列