143. 最大异或对

在这里插入图片描述
思路:
先想暴力的方法,然后进行优化
暴力:

for (int i = 0; i < n; i++)
{
    for (int j = 0; j < n; j++)
    {
        // 但其实 a[i] ^ a[j] == a[j] ^ a[i]
        // 所以内层循环 j < i // 因为 a[i] ^ a[i] == 0 所以事先把返回值初始化成0 不用判断相等的情况
    }
}

利用trie树:
trie树中要明确两个问题:

son[N][x]是个啥?idx是个啥?

首先son[N][x]这是个二维数组。

第一维N是题目给的数据范围,像在trie树中的模板题当中N为字符串的总长度(这里的总长度为所有的字符串的长度加起来),在本题中N需要自己计算,最大为N*31(其实根本达不到这么大,举个简单的例子假设用0和1编码,按照前面的计算最大的方法应该是4乘2=8但其实只有6个结点)。

第二维x代表着儿子结点的可能性有多少,模板题中是字符串,而题目本身又限定了均为小写字母所以只有26种可能性,在本题中下一位只有0或者1两种情况所以为2。

而这个二维数组本身存的是当前结点的下标,就是N喽,所以总结的话son[N][x]存的就是第N的结点的x儿子的下标是多少,然后idx就是第一个可以用的下标。
在这里插入图片描述
模板参考:Trie字符串统计

代码:

# include<iostream>
# include<algorithm>
# include<cstdio>
using namespace std;

const int N = 100010,M = 3100010;
int son[M][2],idx;
//M代表一个数字串二进制可以到多长
int a[N];

void insert(int x)
{
    int p = 0;//根节点
    for(int i = 30;i >= 0;i--)
    {
        int u = x >> i & 1;//取X的第i位的二进制数是什么  x>>k&1(前面的模板)
        if(!son[p][u]) son[p][u] = ++idx;//如果插入中发现没有该子节点,开出这条路
        p = son[p][u];//指针指向下一层
    }
}

int query(int x)
{
    int p = 0, res = 0;
    //从最大位开始找
    for (int i = 30; i >= 0; i -- )
    {
        int s = x >> i & 1;
        if (son[p][!s])//如果当前层有对应的不相同的数
        {
            res += 1 << i;//*2相当左移一位  然后如果找到对应位上不同的数res+1
            p = son[p][!s];//p指针就指到不同数的地址
        }
        else p = son[p][s];
    }
    return res;
}

int main()
{
    int n;
    cin >> n;
    for(int i = 0;i < n;i++)
    {
        cin >> a[i];
        insert(a[i]);
    }
    int res = 0;
    for(int i = 0;i < n;i++)
    {
        res = max(res,query(a[i]));
    }
    cout << res << endl;
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值