算法基础集训(第26天,共106天)------>彻底搞懂Trie树之【最大异或对】,附详细思路和图文代码解析

048eb45522f3401c9e9b963d08eb5a82.gif

目录

一:概念定义 

 

二:题目描述 

 

三:思路分析 

 

四:万年无误代码模板 (含详细解析)

 


一:概念定义 

异或:两个数字转化为二进制数,从低位开始进行异或运算。异或也算也可称之为不进位加法。这题和上一题字符串统计有异曲同工之妙,两者一起食用效果较好。


二:题目描述 

在给定的 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.两个数字异或要尽可能大,则要求两个数字转化为二进制之后,其对应数位的数字要尽可能不同。

 

画一个图帮助理解内部实现:

 

fd588390fc70494698ca547e604ca6a5.png

 


四:万年无误代码模板 (含详细解析)

#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;
}

 创作不易,建议点赞+收藏+关注,以免找不到宝贝文章了。

基础集训结束后将开展拔高系列

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码kobe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值