开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第27天,点击查看活动详情
2.3.4解题
0-1字典树实现好后,这道题那就很简单了,我们把数组每个元素都放入0-1字典树当中,每次插入x时都计算一下x的最大异或值,并使用ans保存每次插入中的最大异或值,最终ans即所求。
实现代码:
java:
import java.util.*;
//结点类
class TireNode {
public TireNode[] next = new TireNode[2];
public TireNode() {}
}
//Tire类
class Tire {
//根结点
public TireNode root = new TireNode();
//插入操作
public void insert(int val) {
TireNode cur = root;
for (int i = 30; i >= 0; --i) {
//获取第i位的二进制数
int u = (val >> i) & 1;
//如果不存在则创建
if (cur.next[u] == null) cur.next[u] = new TireNode();
//更新cur
cur = cur.next[u];
}
}
//查询操作 返回val异或最大时的另外一个操作数
public int query(int val) {
TireNode cur = root;
//储存最大异或操作数的值
int res = 0;
for (int i = 30; i >= 0; --i) {
//获取对应位的二进制
int t = (val >> i) & 1;
//与t不同的二进制
int u = -t + 1;
if (cur.next[u] != null) {
//优先选择不同位
res = res * 2 + u;
cur = cur.next[u];
} else {
//下策选择相同位
res = res * 2 + t;
cur = cur.next[t];
}
}
return res;
}
}
//Main类
class Main {
private static Tire tire = new Tire();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int ans = 0;
int n = sc.nextInt();
while (n-- > 0) {
int a = sc.nextInt();
//插入操作
tire.insert(a);
//查询最大异或值
int ret = tire.query(a) ^ a;
ans = ret > ans ? ret : ans;
}
//输出
System.out.println(ans);
}
}
c++:
const int N = (int) 1e6 + 2333, M = 31 * N;
//结点
class TireNode
{
public:
TireNode* next[2] = {nullptr};
TireNode() {}
};
//Tire类
class Tire
{
public:
//根结点
TireNode* root = new TireNode();
//插入操作
void insert(int val)
{
TireNode* cur = root;
for (int i = 30; i >= 0; --i)
{
//获取第i位的二进制
int u = (val >> i) & 1;
//如果对应的next元素为空,则新增
if (cur->next[u] == nullptr) cur->next[u] = new TireNode();
//更新cur
cur = cur->next[u];
}
}
//查询操作 返回与val异或最大时的另外一个操作数
int query(int val)
{
TireNode* cur = root;
int res = 0;
for (int i = 30; i >= 0; --i)
{
//获取第i位的二进制
int t = (val >> i) & 1;
//获取与t不同的二进制位
int u = -t + 1;
if (cur->next[u] != nullptr)
{
//优先选择不同位
res |= (u << i);
cur = cur->next[u];
} else
{
//迫不得已选相同
res |= (t << i);
cur = cur->next[t];
}
}
return res;
}
};
class Solution {
public:
int findMaximumXOR(vector<int>& nums) {
Tire tire;
int ans = 0;
for (int x : nums)
{
tire.insert(x);
int t = tire.query(x);
int ret = t ^ x;
ans = max(ret, ans);
}
return ans;
}
};
2.3.5使用数组实现0-1字典树
当然在竞赛当中常常使用数组来实现0-1字典树,按照插入顺序为每个结点idx编号即可,N为字符串的所有输入字符串的最大长度,所以字典树的结点个数最大为N,那么最多可能也就是有N个next数组,代码中nes二维数组表示对应着前面的next数组,只不过把所有的结点的next数组都集中在一起罢了,所以我们也可以使用编号为每一个结点分配next数组。
Java代码:
class Solution {
//使用数组实现
private static final int N = (int) 1e5 + 233;
private static final int M = 31 * N;
private static int[][] nes = new int[M][2];
//结点id
private static int idx;
//插入
private static void insert(int val) {
int cur = 0;
for (int i = 30; i >= 0; i--) {
int t = (val >> i) & 1;
if (nes[cur][t] == 0) nes[cur][t] = ++idx;
cur = nes[cur][t];
}
}
//查询最大的异或值
private static int query(int val) {
int cur = 0;
int ret = 0;
for (int i = 30; i >= 0; i--) {
int t = (val >> i) & 1;
//获取不同的位
int u = -t + 1;
//从高位开始找,优先找不同的位
if (nes[cur][u] != 0) {
ret = ret * 2 + u;
cur = nes[cur][u];
} else {
ret = ret * 2 + t;
cur = nes[cur][t];
}
}
return ret;
}
//初始化
public Solution() {
for (int i = 0; i <= idx; i++) {
Arrays.fill(nes[i], 0);
}
idx = 0;
}
public int findMaximumXOR(int[] nums) {
//建树
int ans = 0;
for (int i = 0; i < nums.length; i++) {
insert(nums[i]);
//查询最大异或值
int t = query(nums[i]);
int xor = t ^ nums[i];
//System.out.println(nums[i]);
ans = Math.max(xor, ans);
}
return ans;
}
}
C++实现代码:
const int N = (int) 1e6 + 2333;
int nes[N][2];
int ends[N];
int idx;
class Solution {
private:
void insert(int val) {
int cur = 0;
for (int i = 30; i >= 0; --i) {
int t = (val >> i) & 1;
if (nes[cur][t] == 0) nes[cur][t] = ++idx;
cur = nes[cur][t];
}
}
int query(int val) {
int cur = 0;
int ret = 0;
for (int i = 30; i >= 0; --i) {
int t = (val >> i) & 1;
int u = -t + 1;
if (nes[cur][u] != 0) {
ret |= (u << i);
cur = nes[cur][u];
} else {
ret |= (t << i);
cur = nes[cur][t];
}
}
return ret;
}
public:
Solution() {
for (int i = 0; i <= idx; i++) {
memset(nes[i], 0, sizeof(nes[i]));
}
idx = 0;
}
int findMaximumXOR(vector<int>& nums) {
int ans = 0;
for (int val : nums) {
insert(val);
int ret = query(val) ^ val;
ans = ret > ans ? ret : ans;
}
return ans;
}
};