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

LeetCode 421 - 数组中两个数的最大异或值

在这里插入图片描述
在这里插入图片描述

文章目录

    • 摘要
    • 描述
    • 题解答案
    • 题解代码分析
      • 代码逐步解析
        • ① TrieNode 定义
        • ② 插入数字到 Trie
        • ③ 查找最大异或结果
        • ④ 遍历所有数字求最大值
    • 示例测试及结果
    • 时间复杂度
    • 空间复杂度
    • 总结

摘要

这题的名字叫「数组中两个数的最大异或值」,看起来像是个普通的数学题,
但实际上这是个经典的位运算 + 前缀树优化问题

直观暴力法就是两两异或一遍再取最大值,
但那样是 O(n²) 的复杂度,数组长度一大直接炸掉。

而高效做法是用「Trie(前缀树)」按二进制位去存每个数,
然后每次在树里找一个最能让当前数异或结果更大的路径
最后就能在 O(32n) 的复杂度内解决问题。

本文我们会用 Swift 实现一个完整的解法,并带上运行示例与实战分析。

描述

题目要求:

给定一个整数数组 nums,返回数组中任意两个数 nums[i] XOR nums[j] 的最大值。

其中异或运算(^)的规则是:

  • 相同为 0,不同为 1。

举个例子
5 (0101)25 (11001) 的异或是:

0101
11001
-----
11100 (28)

结果就是 28。

所以题目等价于:

找到一对数字,它们在二进制每个位上尽量不同。

题解答案

这题有两种常见思路

暴力法
两层循环,枚举所有 (i, j) 组合,取最大 nums[i] ^ nums[j]
复杂度 O(n²),当 n = 2×10⁵ 时,完全不可行。

字典树法(Trie)

  • 把每个数字的二进制表示插入到一棵二叉 Trie 树中(0/1 分支);
  • 对每个数,从高位到低位尝试在 Trie 中找「相反位」;
  • 这样就能最大化异或结果。

我们选择第二种方法,效率高又优雅。

题解代码分析

下面是完整的 Swift 版本(可以直接在 Xcode Playground 运行)

import Foundationclass TrieNode {var children: [Int: TrieNode] = [:]
}class Solution {func findMaximumXOR(_ nums: [Int]) -> Int {let root = TrieNode()// 将数字插入Triefunc insert(_ num: Int) {var node = rootfor i in stride(from: 31, through: 0, by: -1) {let bit = (num >> i) & 1if node.children[bit] == nil {node.children[bit] = TrieNode()}node = node.children[bit]!}}// 查找最大异或func query(_ num: Int) -> Int {var node = rootvar xorValue = 0for i in stride(from: 31, through: 0, by: -1) {let bit = (num >> i) & 1// 想异或最大,就尽量找相反位let toggledBit = 1 - bitif let next = node.children[toggledBit] {xorValue |= (1 << i)node = next} else if let next = node.children[bit] {node = next}}return xorValue}// 主流程var maxXor = 0for num in nums {insert(num)}for num in nums {maxXor = max(maxXor, query(num))}return maxXor}
}

代码逐步解析

① TrieNode 定义
class TrieNode {var children: [Int: TrieNode] = [:]
}

每个节点最多有两个分支:

  • children[0] 表示当前位是 0
  • children[1] 表示当前位是 1
② 插入数字到 Trie
for i in stride(from: 31, through: 0, by: -1) {let bit = (num >> i) & 1...
}

我们把每个数的 32 位二进制从高到低依次插入,
确保 Trie 里保留所有数字的二进制路径。

举例:插入 5 (000...0101) 时:

root└─0└─0...└─1└─0└─1
③ 查找最大异或结果
let toggledBit = 1 - bit
if let next = node.children[toggledBit] {xorValue |= (1 << i)node = next
}

遍历当前数字时,

  • 如果能走相反的分支(1-bit),就走那边(这样该位异或能得到 1);
  • 否则只能走相同的分支。

这就是让异或值尽量变大的贪心策略。

④ 遍历所有数字求最大值
for num in nums {maxXor = max(maxXor, query(num))
}

对每个数字都查一遍,找到能和它异或最大的结果。

示例测试及结果

我们来跑几个示例

let solution = Solution()
print(solution.findMaximumXOR([3,10,5,25,2,8]))     // 输出: 28
print(solution.findMaximumXOR([14,70,53,83,49,91,36,80,92,51,66,70])) // 输出: 127
print(solution.findMaximumXOR([0]))                 // 输出: 0
print(solution.findMaximumXOR([2,4]))               // 输出: 6

输出结果

28
127
0
6

可以看到完全符合题目预期。
例如 [3,10,5,25,2,8] 中,5 ^ 25 = 28 确实是最大异或值。

时间复杂度

  • 构建 Trie:O(n × 32)
  • 查询每个数最大异或值:O(n × 32)

总时间复杂度:O(32n) ≈ O(n)

空间复杂度

Trie 树的节点最多为 32 × n 个。
空间复杂度:O(32n) ≈ O(n)

总结

这道题是「位运算 + Trie 树」的经典题型。
它的核心思想是:

利用二进制前缀树在每一位上做“相反匹配”,
让异或的每一位都尽量为 1,从而得到最大值。

在实际开发中,这种思想常用于:

  • 网络掩码匹配(IP 地址的前缀匹配);
  • 路由查找;
  • 加密或压缩算法中位优化。

Swift 实现虽然看起来略繁琐,但逻辑其实非常清晰:
结构体化思维 + 位运算配合字典树,是一种非常高效且优雅的解法。

http://www.dtcms.com/a/596277.html

相关文章:

  • 【笔记】xFormers版本与PyTorch、CUDA对应关系及正确安装方法详解
  • 【GitHub每日速递 20251111】PyTorch:GPU加速、动态网络,深度学习平台的不二之选!
  • 多产品的网站怎么做seo做音乐网站之前的准备
  • 网站如何做h5动态页面设计万网备案初审过了后网站能访问吗
  • centos运维常用命令
  • 在CentOS 7.6系统中找回或重置 root 密码
  • 濮阳团购网站建设手机网站模板psd
  • 基于Spring Boot的电子犬证管理系统设计与实现
  • Spring Boot 中的定时任务:从基础调度到高可用实践
  • 家装设计师网站wordpress小清新模板
  • 用WordPress制作单页相城seo网站优化软件
  • wordpress主题wpmee江门网站优化排名
  • 淮安设计网站苏州网站建设相关技术
  • 公司的网站开发费计入什么科目济南传承网络李聪
  • 营销类型的公司网站物联网平台功能
  • 做网站设计都需要什么杭州建设信息网
  • 惠州网站设计哪家好网站内的搜索怎么做的
  • 网站域名使用费用上海十大猎头公司排名
  • 网站建站程序wordpress salient
  • 舞蹈网站模板权威做网站的公司
  • 互联网 创新创业大赛seo推广培训中心
  • 广西网站建设-好发信息网建设银行网站e动终端
  • 建站网哪个好微信公众号调用WordPress
  • 广州网站建设比较好的公司主营网站建设会计记账
  • 招生网站建设板块网站建设的针对对象
  • 成都访问公司网站吉安工商注册官方网站
  • 网站建设暨检务公开自查报告昆山网站维护
  • 淘宝领券网站怎么做网站基本配置
  • 人人做网站做网站用什么语言高效
  • 企业网站seo优化公司对网站建设好学吗