LeetCode题练习与总结:数组中两个数的最大异或值--421

一、题目描述

给你一个整数数组 nums ,返回nums[i] XOR nums[j] 的最大运算结果,其中 0 ≤ i ≤ j < n

示例 1:

复制代码
输入:nums = [3,10,5,25,2,8]
输出:28
解释:最大运算结果是 5 XOR 25 = 28.

示例 2:

复制代码
输入:nums = [14,70,53,83,49,91,36,80,92,51,66,70]
输出:127

提示:

  • 1 <= nums.length <= 2 * 10^5
  • 0 <= nums[i] <= 2^31 - 1

二、解题思路

这个问题可以通过字典树(Trie)来解决。字典树是一种树形结构,用于高效地存储和检索字符串数据集中的键。在这个问题中,我们可以将每个整数的二进制表示视为字符串,然后构建一个字典树来存储这些二进制字符串。

步骤如下:

  1. 将所有数字转换为二进制字符串,并从最高位开始构建字典树。
  2. 对于每个数字,尝试找到字典树中与之异或结果最大的数字。具体来说,就是从最高位开始,尽可能选择与当前位相反的路径(如果存在的话)。
  3. 记录过程中遇到的最大异或结果。

三、具体代码

java 复制代码
class Solution {
    class TrieNode {
        TrieNode[] children = new TrieNode[2];
    }

    public int findMaximumXOR(int[] nums) {
        // 初始化字典树的根节点
        TrieNode root = new TrieNode();
        // 将所有数字插入字典树
        for (int num : nums) {
            TrieNode cur = root;
            for (int i = 31; i >= 0; i--) {
                int bit = (num >> i) & 1;
                if (cur.children[bit] == null) {
                    cur.children[bit] = new TrieNode();
                }
                cur = cur.children[bit];
            }
        }

        int max_xor = 0;
        // 对于每个数字,尝试找到与之异或结果最大的数字
        for (int num : nums) {
            TrieNode cur = root;
            int xor = 0;
            for (int i = 31; i >= 0; i--) {
                int bit = (num >> i) & 1;
                // 尝试选择与当前位相反的路径
                if (cur.children[1 - bit] != null) {
                    xor = (xor << 1) | 1;
                    cur = cur.children[1 - bit];
                } else {
                    xor = xor << 1;
                    cur = cur.children[bit];
                }
            }
            max_xor = Math.max(max_xor, xor);
        }
        return max_xor;
    }
}

这段代码首先构建了一个字典树,然后对于每个数字,通过字典树找到了与之异或结果最大的数字,并记录下最大异或结果。最终返回这个最大异或结果。

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 构建字典树:对于数组中的每个数字,我们需要遍历它的32位(假设整数为32位),并将每一位插入到字典树中。如果数组长度为n,那么构建字典树的时间复杂度为O(n * 32)。

  • 查找最大异或值:同样地,对于数组中的每个数字,我们需要遍历它的32位,并在字典树中查找与之异或结果最大的数字。这个过程的时间复杂度也是O(n * 32)。

将这两个步骤合并,总的时间复杂度为O(n * 32),可以简化为O(n)。

2. 空间复杂度
  • 字典树节点:在最坏的情况下,如果所有数字的二进制表示都不同,字典树中的节点数将达到最大。每个数字有32位,每一位有两种可能(0或1),所以字典树中的节点数最多为2^32,这是一个常数,与输入数组的大小无关。

  • 字典树结构:字典树的结构本身不依赖于输入数组的大小,它只依赖于数字的位数,这里为32位。

因此,空间复杂度为O(1),即常数空间复杂度,因为字典树的大小不会随着输入数组的大小而变化。

五、总结知识点

  • 字典树(Trie)

    • 字典树是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。
    • 在这个问题中,字典树用于存储数字的二进制表示。
  • 位操作

    • 使用位操作来获取数字的每一位,例如 (num >> i) & 1 用于获取数字 num 的第 i 位。
    • 使用位移操作 << 和按位或操作 | 来构建异或结果。
  • 递归与迭代

    • 代码中使用了迭代而非递归来遍历字典树。
  • 贪心算法

    • 在寻找最大异或值时,代码采用了贪心策略,即每次都试图选择与当前位相反的路径,以获得更大的异或值。
  • 树的遍历

    • 通过遍历字典树来查找与给定数字异或结果最大的数字。
  • 数组的使用

    • TrieNode 类中的 children 数组用于存储子节点,每个节点有两个子节点,分别对应二进制位 0 和 1。
  • 类的定义与实例化

    • TrieNode 类的定义和实例化,以及它在 Solution 类中的使用。
  • 循环与条件判断

    • 使用 for 循环来遍历数组中的每个数字,以及遍历数字的每一位。
    • 使用 if-else 语句来决定在字典树中走哪条路径。
  • 最大值的查找

    • 使用 Math.max 函数来更新最大异或值。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

相关推荐
想不明白的过度思考者2 分钟前
Java从入门到“放弃”(精通)之旅——JavaSE终篇(异常)
java·开发语言
.生产的驴26 分钟前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven
猿周LV34 分钟前
JMeter 安装及使用 [软件测试工具]
java·测试工具·jmeter·单元测试·压力测试
知来者逆36 分钟前
计算机视觉——速度与精度的完美结合的实时目标检测算法RF-DETR详解
图像处理·人工智能·深度学习·算法·目标检测·计算机视觉·rf-detr
晨集36 分钟前
Uni-App 多端电子合同开源项目介绍
java·spring boot·uni-app·电子合同
时间之城38 分钟前
笔记:记一次使用EasyExcel重写convertToExcelData方法无法读取@ExcelDictFormat注解的问题(已解决)
java·spring boot·笔记·spring·excel
阿让啊40 分钟前
C语言中操作字节的某一位
c语言·开发语言·数据结构·单片机·算法
এ᭄画画的北北41 分钟前
力扣-160.相交链表
算法·leetcode·链表
椰羊~王小美1 小时前
LeetCode -- Flora -- edit 2025-04-25
java·开发语言
凯酱1 小时前
MyBatis-Plus分页插件的使用
java·tomcat·mybatis