目录

1707:与数组中元素的最大异或值(2358 分)

力扣第 221 场周赛第 4 题

题目

给你一个由非负整数组成的数组 nums 。另有一个查询数组 queries ,其中 queries[i] = [xi, mi]

i 个查询的答案是 xi 和任何 nums 数组中不超过 mi 的元素按位异或(XOR)得到的最大值。换句话说,答案是 max(nums[j] XOR xi) ,其中所有 j 均满足 nums[j] <= mi 。如果 nums 中的所有元素都大于 mi,最终答案就是 -1

返回一个整数数组 answer 作为查询的答案,其中 answer.length == queries.length answer[i] 是第 i 个查询的答案。

示例 1:

输入:nums = [0,1,2,3,4], queries = [[3,1],[1,3],[5,6]]
输出:[3,3,7]
解释:
1) 0 和 1 是仅有的两个不超过 1 的整数。0 XOR 3 = 3 而 1 XOR 3 = 2 。二者中的更大值是 3 。
2) 1 XOR 2 = 3.
3) 5 XOR 2 = 7.

示例 2:

输入:nums = [5,2,4,6,6,3], queries = [[12,4],[8,1],[6,3]]
输出:[15,-1,5]

提示:

  • 1 <= nums.length, queries.length <= 105
  • queries[i].length == 2
  • 0 <= nums[j], xi, mi <= 109

相似问题:

分析

  • 0421 升级版,区别是只查询 <=m 的元素
  • 一种常用的方法是将查询和元素都排序,保证整个查询过程中元素只加不减
  • 在这个过程中,动态构建哈希表或字典树,即转为 0421

解答

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class Solution:
    def maximizeXor(self, nums: List[int], queries: List[List[int]]) -> List[int]:
        L = max(nums+[x for x,_ in queries]).bit_length()
        T = [set() for _ in range(L)]
        nums.sort()
        j = 0
        res = [-1]*len(queries)
        for i,(x,m) in sorted(enumerate(queries),key=lambda p:p[1][1]):
            while j<len(nums) and nums[j]<=m:
                for k in range(L):
                    T[k].add(nums[j]>>k)
                j += 1
            if j:
                y = 0
                for k in range(L-1,-1,-1):
                    y <<= 1
                    y += (y+1)^(x>>k) in T[k]
                res[i] = y
        return res

1565 ms

*附加

字典树写法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class BitTrie:
    def __init__(self,n,L):                       # 插入总长度 n-1、最长 L 的二进制串
        self.t = [[0]*n for _ in range(2)]        # 模拟树节点
        self.i = 0
        self.L = L

    def add(self, x):
        p = 0
        for j in range(self.L-1, -1, -1):
            bit = (x>>j)&1
            if not self.t[bit][p]:
                self.i += 1
                self.t[bit][p] = self.i  
            p = self.t[bit][p]

    def maxxor(self,x):
        p = 0
        res = 0
        for j in range(self.L-1, -1, -1):
            bit = (x>>j)&1
            if self.t[bit^1][p]:
                res |= 1 << j
                bit ^= 1
            p = self.t[bit][p]
        return res

class Solution:
    def maximizeXor(self, nums: List[int], queries: List[List[int]]) -> List[int]:
        L = max(nums+[x for x,_ in queries]).bit_length()
        trie = BitTrie(len(nums)*L+1,L)
        nums.sort()
        j = 0
        res = [-1]*len(queries)
        for i,(x,m) in sorted(enumerate(queries),key=lambda p:p[1][1]):
            while j<len(nums) and nums[j]<=m:
                trie.add(nums[j])
                j += 1
            if j:
                res[i] = trie.maxxor(x)
        return res

1753 ms