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


文章目录

摘要

这题的名字叫「数组中两个数的最大异或值」,看起来像是个普通的数学题,

但实际上这是个经典的位运算 + 前缀树优化问题。

直观暴力法就是两两异或一遍再取最大值,

但那样是 O(n²) 的复杂度,数组长度一大直接炸掉。

而高效做法是用「Trie(前缀树)」按二进制位 去存每个数,

然后每次在树里找一个最能让当前数异或结果更大的路径 ,

最后就能在 O(32n) 的复杂度内解决问题。

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

描述

题目要求:

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

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

  • 相同为 0,不同为 1。

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

txt 复制代码
0101
11001
-----
11100 (28)

结果就是 28。

所以题目等价于:

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

题解答案

这题有两种常见思路

暴力法

两层循环,枚举所有 (i, j) 组合,取最大 nums[i] ^ nums[j]。

复杂度 O(n²),当 n = 2×10⁵ 时,完全不可行。

字典树法(Trie)

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

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

题解代码分析

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

swift 复制代码
import Foundation

class TrieNode {
    var children: [Int: TrieNode] = [:]
}

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

代码逐步解析

① TrieNode 定义
swift 复制代码
class TrieNode {
    var children: [Int: TrieNode] = [:]
}

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

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

我们把每个数的 32 位二进制从高到低依次插入,

确保 Trie 里保留所有数字的二进制路径。

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

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

遍历当前数字时,

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

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

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

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

示例测试及结果

我们来跑几个示例

swift 复制代码
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

输出结果

txt 复制代码
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 实现虽然看起来略繁琐,但逻辑其实非常清晰:

结构体化思维 + 位运算配合字典树,是一种非常高效且优雅的解法。

相关推荐
倒头就睡的小比特4 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!4 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼4 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光4 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark4 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her14 天前
并查集-听课笔记
笔记·算法·并查集
码流子4 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven4 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark4 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218614 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法