- 概述
字典树/前缀树是一种利用字符串的公共前缀来减少查询时间的树形结构,查询效率高,但存储空间消耗比较大。
- 经典应用
- 异或问题
- 例题1:异或问题
给你一个由非负整数组成的数组 nums 。另有一个查询数组 queries ,其中 。
第 i 个查询的答案是 和任何 nums 数组中不超过
的元素按位异或(XOR)得到的最大值。换句话说,答案是
,其中所有 j 均满足
。如果 nums 中的所有元素都大于
,最终答案就是 -1 。
返回一个整数数组 answer 作为查询的答案,其中 answer.length == queries.length 且 answer[i] 是第 i 个查询的答案。
题目来源:Leetcode1707题
题目链接:https://leetcode-cn.com/problems/maximum-xor-with-an-element-from-array
分析:
本题数据量较大,需要进行离线查询。将nums数据从小到大排序后再将queries中的数据从小到大排序。每次只插入比当前查询的小的数。查询的时候尽可能使得高位不相同。
参考解答:
class Solution:def maximizeXor(self, nums: List[int], queries: List[List[int]]) -> List[int]:nums.sort()q = [(m, x, idx) for idx, (x, m) in enumerate(queries)]q.sort()i = 0ret = [0] * len(q)trie = Trie()for m, x, idx in q:while i < len(nums) and nums[i] <= m:trie.insert(nums[i])i += 1ret[idx] = trie.getXor(x)return retclass TrieNode:def __init__(self) -> None:self.val = -1self.next = {}def binaryStr(val):s = bin(val)[2:] # 转化为2进制后前面两个字符为0b,故去掉n = len(s)return '0' * (32-n) + sclass Trie:def __init__(self) -> None:self.root = TrieNode()def insert(self, num):binary = binaryStr(num)cur = self.rootfor c in binary:if c not in cur.next:cur.next[c] = TrieNode()cur = cur.next[c]cur.val = numdef getXor(self, num):cur = self.rootif not cur.next:return -1binary = binaryStr(num)for c in binary:if c == '0':cur = cur.next['1'] if '1' in cur.next else cur.next['0']elif c == '1':cur = cur.next['0'] if '0' in cur.next else cur.next['1']return cur.val ^ num
- 练习题
- 数组中两个数的最大异或值
题目来源:Leetcode421题
题目链接:https://leetcode-cn.com/problems/maximum-xor-of-two-numbers-in-an-array/
参考解答:
class TrieNode:def __init__(self):self.next = {}self.val = -1def buildBinary(num):s = bin(num)[2:]n = len(s)binary = '0' * (32 - n) + sreturn binaryclass Solution:def findMaximumXOR(self, nums: List[int]) -> int:root = TrieNode()for num in nums:cur = rootbinary = buildBinary(num)for c in binary:if c not in cur.next:cur.next[c] = TrieNode()cur = cur.next[c]cur.val = numans = 0for num in nums:cur = rootbinary = buildBinary(num)for c in binary:if c == '0':cur = cur.next['1'] if '1' in cur.next else cur.next['0']elif c == '1':cur = cur.next['0'] if '0' in cur.next else cur.next['1']ans = max(ans, cur.val ^ num)return ans
