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 函数来更新最大异或值。

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

相关推荐
va学弟1 分钟前
Agent入门开发(2):个性化功能添加
java·服务器·ai
Rabitebla2 分钟前
【数据结构】消失的数字+ 轮转数组:踩坑详解
c语言·数据结构·c++·算法·leetcode
8486981192 分钟前
Cursor 用 Java + Vue3 做了一个可落地的酒店管理系统(HMS),支持多门店、RBAC、财务结算,源码开源!
java·开发语言·开源
菜菜的顾清寒4 分钟前
力扣100(20)旋转图像
算法·leetcode·职场和发展
Navigator_Z4 分钟前
LeetCode //C - 1025. Divisor Game
c语言·算法·leetcode
深念Y4 分钟前
王者荣耀与英雄联盟数值设计对比:穿透、乘算与加算、增伤乘算更厉害,减伤加算更厉害
数学·算法·游戏·建模·游戏策划·moba·数值
budingxiaomoli12 分钟前
优选算法-多源bfs解决拓扑排序问题
算法·宽度优先
隔壁大炮12 分钟前
10.PyTorch_元素类型转换
人工智能·pytorch·深度学习·算法
The Chosen One98512 分钟前
算法题目分享(二分算法)
算法·职场和发展·蓝桥杯
程序员老邢13 分钟前
【技术底稿 23】Ollama + Docker + Ubuntu 部署踩坑实录:网络通了,参数还在调
java·经验分享·后端·ubuntu·docker·容器·milvus