java对ac_AcWing 143. 最大异或对(Java)

题目描述

自己看题了 最大异或对

能来看我题解的,想必都看过Y总的课程了。

我就说说我对这个Trie树算法解的两个问题

1、son[n][m]怎么理解,位移数位个数为什么是从30 - 0右移?

2、Trie树的构建逻辑

3、Trie的查询逻辑

算法

1、 son数组定义是二维数组,son[n][m]我在初学Trie树的时候很难理解,可以先理解它的第二维度,只有两种状态0/1,是因为这一位表示的是某个数字的的某一位是0 / 1,而第一维的大小是我们用的十足二进制表示下一共有多少位数,在本题中,数字一共有N个数字,N是小于$10^5$的,一个数在int下是32位,则我们需要至少3200000的一维坐标,而p = son[n][0] / p = son[n][1]其实存的值就是他的两个子节点的一维坐标的值。

那么x >> i & 1 其实就是我想知道x的二进制表示中的第i位(二进制位从第0位开始表示第0位 - 第 31 位),本题的题目范围到2^31那么就是i从30 - 0。

2、构建逻辑其实相对简单,就是将数的二进制表示插入到son数组中,如果没有那么就将他的值附上++idx即可

3、查询的时候为了异或大小最大,那么就应该从根节点开始遍历最高位开始尽量让异或结果为1,在遍历查询数字的第i位的时候取第i位的值为s,查看son[p][!s]是否存在,如果存在那么将res+= i << i(这一位异或存在最大值为1),如果没有那么就让p = son[p]s。

记得点赞啊!

时间复杂度 $O(nlogn)$

参考文献

Java 代码

import java.util.*;

import java.io.*;

class Main{

static int idx;

static int[][] son = new int[3000000][2];

static void insert(int x){

int p = 0;

for(int i = 30; i >= 0; i--){

if(son[p][(x >> i) & 1] == 0){

son[p][(x >> i) & 1] = ++ idx;

}

p = son[p][(x >> i) & 1];

}

}

static int query(int x){

int p = 0, res = 0;

for(int i = 30; i >= 0; i--){

int s = (x >> i) & 1;

if(son[p][1-s] != 0){

res += (1 << i);

p = son[p][1-s];

}else{

p = son[p][s];

}

}

return res;

}

public static void main(String[] args) throws Exception{

Scanner sc = new Scanner(System.in);

int n = sc.nextInt();

int[] a = new int[n];

for(int i = 0; i < n; i++){

a[i] = sc.nextInt();

insert(a[i]);

}

int res = 0;

for(int num : a){

res = Math.max(res, query(num));

}

System.out.println(res);

}

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值