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

【数据结构-异或字典树】力扣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

在这里插入图片描述

字典树

struct Trie{
    Trie* left = nullptr;
    Trie* right = nullptr;
    Trie(){}
};


class Solution {
private:
    Trie* root = new Trie();
    static constexpr int HIGH_BIT = 30;

public:
    void add(int num){
        Trie* cur = root;
        for(int k = HIGH_BIT; k >= 0; k--){
            int bit = (num >> k) & 1;
            if(bit == 0){
                if(cur->left == nullptr){
                    cur->left = new Trie();
                }
                cur = cur->left;
            }
            else{
                if(cur->right == nullptr){
                    cur->right = new Trie();
                }
                cur = cur->right;
            }
        }
    }

    int check(int num){
        Trie* cur = root;
        int x = 0;
        for(int k = HIGH_BIT; k >= 0; k--){
            int bit = (num >> k) & 1;
            if(bit == 0){
                if(cur->right){
                    cur = cur->right;
                    x = x * 2 + 1;
                }
                else{
                    cur = cur->left;
                    x = x * 2;
                }
            }
            else{
                if(cur->left){
                    cur = cur->left;
                    x = x * 2 + 1;
                }
                else{
                    cur = cur->right;
                    x = x * 2;
                }
            }
        }
        return x;
    }

    int findMaximumXOR(vector<int>& nums) {
        int x = 0;
        for(int j = 1; j < nums.size(); j++){
            add(nums[j-1]);
            x = max(x, check(nums[j]));
        }
        return x;
    }
};

时间复杂度:O(nlogC),其中 n 是数组 nums 的长度,C 是数组中的元素范围。

空间复杂度:O(nlogC)。每一个元素在字典树中需要使用 O(logC) 的空间,因此总空间复杂度为 O(nlogC)。

这道题我们可以使用字典树来完成,我们枚举j,然后将nums[0]到nums[j-1]的元素都加入到字典树中。

接着我们将nums[j]传入check函数中来在已经构造的字典树中找到一个最符合的路径。我们使用贪心的思想,我们要让他异或的值最大,那么就要优先在较高的bit位上找出与nums[j]对应比特位相反数值的路径。也就是说在某个比特位上,nums[j]的该比特位是1,也就是代表树中的right,那么我们就要优先走0,也就是left这条路径。如果left路径不存在的话再选择走right路径(由于cur节点存在,那么cur->left或者cur->right必定有一个存在)。只要与nums[j]某比特位相反的节点存在,那么我们就走该子树的路径,由于该比特位会是异或,所以我们的异或值x就要更新为x = x * 2 + 1,如果只存在相同比特位的节点,那么就将x更新为x = x * 2


http://www.kler.cn/a/540885.html

相关文章:

  • 数据仓库和商务智能:洞察数据,驱动决策
  • Git、Github和Gitee完整讲解:丛基础到进阶功能
  • DeepSeek元学习(Meta-Learning)基础与实践
  • ASP.NET Core JWT
  • 【DeepSeek】DeepSeek概述 | 本地部署deepseek
  • C# OpenCvSharp 部署MOWA:多合一图像扭曲模型
  • 【Pandas】pandas Series nunique
  • C++:将函数参数定义为const T的意义
  • 网络编程(预备知识)
  • GaN技术基站需要匹配的高性能电源解决方案
  • 美颜SDK架构设计指南:性能优化与跨平台适配实战
  • 数据可视化与交互融合:APP 界面设计的新维度
  • Python3 ImportError: cannot import name ‘XXX‘ from ‘XXX‘
  • 【Kubernetes的SpringCloud最佳实践】有Service是否还需要Eureka?
  • 【数据结构】双向链表(真正的零基础)
  • Rust 测试组织指南:单元测试与集成测试
  • 前端-导出png,jpg,pptx,svg
  • 【Kubernetes】常用命令全解析:从入门到实战(上)
  • 【Linux】深入理解linux权限
  • 【开源免费】基于SpringBoot+Vue.JS公寓报修管理系统(JAVA毕业设计)
  • VBA语言的软件工程
  • 《LeetCode Hot100》 Day01
  • 常见的前端框架和库有哪些
  • 04:定时器
  • ArcGIS中的空值问题
  • Java中的设计模式应用与最佳实践