当前位置: 首页 > article >正文

最大异或对(每周一类)

        今天我们来看这个最大异或类这道题 最大异或对 

        1.首先,我们先来了解一下异或是什么,之后还要讲一下同或。

        众所周知,数字在计算机中是由二进制来表示的,比如十进制的7,用二进制表示就是 111,十进制的3,用二进制表示就是011,。形象一点表示如下图:

        3与7进行异或操作就是将二进制相同的地方变成0,不同的地方变成1,在示例中,就变成了4。

        简单理解,就异(不一样的地方)变成1,。

        同或就是相反,同(相同的地方)变成1,不相同的地方变成0。

        好,在理解了基础概念再看这道题,就是我们用暴力的方法,就是两重循环,一个个来做异或,比较他们的大小,最后找出最大的异或对。在c++中,异或的运算符号是^,比如要计算a异或b,就写 a ^ b 就好。

        在理解了题意之后,我们来做一下代码(暴力):

#include <iostream>
#include <algorithm>

using namespace std;
const int N = 100010;

int main(){
    int n;
    cin >> n;
    int a[N];
    for(int i = 0; i < n ; i ++ ){
        scanf("%d",&a[i]);
    }
    int res = -1;
    for(int i = 0; i < n ; i ++ ){
        for(int j = i + 1; j < n; j ++ ){
            int x = a[i]^a[j];
            res = max(res,x);
        }
    }
    printf("%d\n",res);
    return 0;
}

        时间复杂度是O(n^2)有点太大了,我们要进行优化,方法就是 Trie 树,由于对于每一个数,我们总有办法找到最好的,能匹配它的数,使得他们的异或值最大,如下图,我们找和十进制的 5 匹配的数字,5变成二进制是101,我们要找的就是二进制是010的数字,就是2。

        按照这个思路,我们在存进去一个数的时候,就可以存储Trie树,当查找最大值的时候,我们就可以对刚刚暴力循环的第二层进行优化之后的查找,效率会更高。具体代码如下:

#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 &s = son[p][x >> i & 1];
        if(!s) s = ++idx;
        p = s;
    }
}
int search(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;
            p = son[p][!s];
        }
        else p = son[p][s];
    }
    return res;
}

int main(){
    int n;
    cin >> 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",res);
    return 0;
}

        和上一节一样,我们存储的时候要定义索引 p ,刚开始是 0 ,随着 idx 的增加,而递增,用于判断不同的数字变成的二进制串,如果输入的串存在,那么就继续;如果不存在,就创建。在查找的时候,如果查找的串存在,就继续,如果不存在,就输出相反字符,比如我们对 101 的 期望是 010,但如果没有 010 ,只有 011,我们就找 011串。

        其中对于每一个数字的处理,我们是从高位到低位进行处理,我们从31到0位进行存入或者查找。

        这节课可以参照着上节课一起看,将Trie树的模版掌握并会自己写,就可以迎刃而解


http://www.kler.cn/news/338981.html

相关文章:

  • 常用动词敬语形式大揭秘,柯桥零基础日语培训
  • 【C#生态园】提升C#图像处理与压缩效率:六款库全面比较
  • jQuery EasyUI 扩展
  • cmakelist加载Qt模块
  • 定时器定时中断定时器外部中断
  • Qt 图片显示 动态选择图片显示
  • 基于springboot的家政服务管理系统(含源码+sql+视频导入教程+文档+PPT)
  • ctfshow-web入门(信息收集,持续更新中。。)
  • JavaSE - 基础语法
  • 【Qt】控件概述(2)—— 按钮类控件
  • Transformer模型
  • [C++ 核心编程]笔记 2 栈区和堆区
  • Ascend C 自定义算子开发:高效的算子实现
  • C语言普及难度三题
  • 今天股市又大涨了,如何操作
  • k8s实战-2
  • JavaSE——面向对象9.1:代码块详解
  • R语言绘制饼图
  • 【Spark 实战】基于spark3.4.2+iceberg1.6.1搭建本地调试环境
  • 信息安全——应急响应