• 概述

    字典树/前缀树是一种利用字符串的公共前缀来减少查询时间的树形结构,查询效率高,但存储空间消耗比较大。

    • 经典应用
      • 异或问题
    • 例题1:异或问题

    给你一个由非负整数组成的数组 nums 。另有一个查询数组 queries ,其中 字典树/前缀树 - 图1
    第 i 个查询的答案是 字典树/前缀树 - 图2 和任何 nums 数组中不超过 字典树/前缀树 - 图3的元素按位异或(XOR)得到的最大值。换句话说,答案是 字典树/前缀树 - 图4 ,其中所有 j 均满足 字典树/前缀树 - 图5 。如果 nums 中的所有元素都大于 字典树/前缀树 - 图6,最终答案就是 -1 。
    返回一个整数数组 answer 作为查询的答案,其中 answer.length == queries.length 且 answer[i] 是第 i 个查询的答案。
    字典树/前缀树 - 图7
    题目来源:Leetcode1707题
    题目链接:https://leetcode-cn.com/problems/maximum-xor-with-an-element-from-array
    分析:
    本题数据量较大,需要进行离线查询。将nums数据从小到大排序后再将queries中的数据从小到大排序。每次只插入比当前查询的字典树/前缀树 - 图8小的数。查询的时候尽可能使得高位不相同。
    参考解答:

    1. class Solution:
    2. def maximizeXor(self, nums: List[int], queries: List[List[int]]) -> List[int]:
    3. nums.sort()
    4. q = [(m, x, idx) for idx, (x, m) in enumerate(queries)]
    5. q.sort()
    6. i = 0
    7. ret = [0] * len(q)
    8. trie = Trie()
    9. for m, x, idx in q:
    10. while i < len(nums) and nums[i] <= m:
    11. trie.insert(nums[i])
    12. i += 1
    13. ret[idx] = trie.getXor(x)
    14. return ret
    15. class TrieNode:
    16. def __init__(self) -> None:
    17. self.val = -1
    18. self.next = {}
    19. def binaryStr(val):
    20. s = bin(val)[2:] # 转化为2进制后前面两个字符为0b,故去掉
    21. n = len(s)
    22. return '0' * (32-n) + s
    23. class Trie:
    24. def __init__(self) -> None:
    25. self.root = TrieNode()
    26. def insert(self, num):
    27. binary = binaryStr(num)
    28. cur = self.root
    29. for c in binary:
    30. if c not in cur.next:
    31. cur.next[c] = TrieNode()
    32. cur = cur.next[c]
    33. cur.val = num
    34. def getXor(self, num):
    35. cur = self.root
    36. if not cur.next:
    37. return -1
    38. binary = binaryStr(num)
    39. for c in binary:
    40. if c == '0':
    41. cur = cur.next['1'] if '1' in cur.next else cur.next['0']
    42. elif c == '1':
    43. cur = cur.next['0'] if '0' in cur.next else cur.next['1']
    44. return cur.val ^ num
    • 练习题
      • 数组中两个数的最大异或值

    题目来源:Leetcode421题
    题目链接:https://leetcode-cn.com/problems/maximum-xor-of-two-numbers-in-an-array/
    参考解答:

    1. class TrieNode:
    2. def __init__(self):
    3. self.next = {}
    4. self.val = -1
    5. def buildBinary(num):
    6. s = bin(num)[2:]
    7. n = len(s)
    8. binary = '0' * (32 - n) + s
    9. return binary
    10. class Solution:
    11. def findMaximumXOR(self, nums: List[int]) -> int:
    12. root = TrieNode()
    13. for num in nums:
    14. cur = root
    15. binary = buildBinary(num)
    16. for c in binary:
    17. if c not in cur.next:
    18. cur.next[c] = TrieNode()
    19. cur = cur.next[c]
    20. cur.val = num
    21. ans = 0
    22. for num in nums:
    23. cur = root
    24. binary = buildBinary(num)
    25. for c in binary:
    26. if c == '0':
    27. cur = cur.next['1'] if '1' in cur.next else cur.next['0']
    28. elif c == '1':
    29. cur = cur.next['0'] if '0' in cur.next else cur.next['1']
    30. ans = max(ans, cur.val ^ num)
    31. return ans