ACWing- 最大异或对

87 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

一、题目描述:

在给定的 NN 个整数 A1,A2……ANA1,A2……AN 中选出两个进行 xorxor(异或)运算,得到的结果最大是多少?

输入格式

第一行输入一个整数 NN。

第二行输入 NN 个整数 A1A1~ANAN。

输出格式

输出一个整数表示答案。

数据范围

截屏2022-04-01 下午7.04.34

输入样例:

3
1 2 3

输出样例:

3

二、思路分析:

这一题是Tire数的一种运用,首先我们先来理解什么样的两个数异或后会成为最大的数

先变为2进制数,然后从最高位开始如果每个数都不相同的话,那么两个数则为最大值

我们可以看到数据的取值范围已经提示了我们可以把数变为二进制储存。

然后我们再距离trie树

 static void inster(int x){
        int p = 0;
        /** 从高位开始,因为是正整数所以最高位为符号位为0,最高有效位为30位 */
        for (int i = 30; i >= 0; i--) {
            /** 看x的第i位为1还是0 */
            int u = x >> i & 1;
          	/** 如果该节点不存在,则创建该节点*/
            if (son[p][u] == 0) {
                son[p][u] = ++ idx;
            }
            /** 让指针指向下一个节点 */
            p = son[p][u];
        }
    }

然后我们再查找每一个数的最大异或数

 static int query(int x){
        int p = 0,tmp = 0;
        for (int i = 30; i >= 0; i--) {
            int u = x >> i & 1;
            if (son[p][u ^ 1] != 0) {
                // 如果相同层存在不同的数,则把1移动到改位再加上
                tmp += 1 << i;
                p = son[p][u^1];
            }
            // 如果不存在就移动到下一个节点(下一层)
            else p = son[p][u];
        }
        return tmp;
    }

三、AC 代码:

import java.util.Scanner;

public class Main{
    static int n;
    static int[] num = null;
    static int[][] son = new int[3100010][2];
    static int idx;
    static int res;

    /** 暴力方法,会超时 */
    // public static void main(String[] args) {
    //     Scanner in = new Scanner(System.in);
    //     n = in.nextInt();

    //     num = new int[n];
    //     for (int i = 0; i < n; i++) {
    //         num[i] = in.nextInt();
    //     }

    //     for (int i = 0; i < num.length; i++) {
    //         for (int j = 0; j < num.length; j++) {
    //             res = Math.max(res, num[i]^num[j]);
    //         }
    //     }

    //     System.out.println(res);
    // }


    static void inster(int x){
        int p = 0;
        /** 从高位开始,因为是正整数所以最高位为符号位为0,最高有效位为30位 */
        for (int i = 30; i >= 0; i--) {
            /** 看x的第i位为1还是0 */
            int u = x >> i & 1;
            if (son[p][u] == 0) {
                son[p][u] = ++ idx;
            }
            /** 让指针指向下一个节点 */
            p = son[p][u];
        }
    }


    static int query(int x){
        int p = 0,tmp = 0;
        for (int i = 30; i >= 0; i--) {
            int u = x >> i & 1;
            if (son[p][u ^ 1] != 0) {
                // 如果相同层存在不同的数,则把1移动到改位再加上
                tmp += 1 << i;
                p = son[p][u^1];
            }
            // 如果不存在就移动到下一个节点(下一层)
            else p = son[p][u];
        }
        return tmp;
    }
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        n = in.nextInt();

        num = new int[n];
        for (int i = 0; i < n; i++) {
            num[i] = in.nextInt();
            inster(num[i]);
        }

        for (int i = 0; i < num.length; i++) {
            res = Math.max(res, query(num[i]));
        }
        System.out.println(res);
    }
}