PS:使用 JS 可以平方复杂度直接莽过。不过这个数据范围平方意味着 $10^(10)$ 次运算,很难想象这是怎么 AC 的。
下面介绍一个 预处理 + 双指针的方法。
不要关心 x 最后和 nums 中的谁异或了,只关心最终异或的数的每一位分别是多少。
以 nums[0,1,2,3,4], x 为 9 为例,给大家讲解一下核心原理。
具体算法:
首先对数据进行预处理,建立一个二维 dp 数组, dp[i][j] 是和 nums[j] 第 i 位相等的最小的数组下标。
为了使用双指针,我们需要对 nums 进行排序
接下来对每一个查询,我们调用 solve 函数计算最大的异或值。
solve 函数内部使用双指针,比较头尾指针和 x 的异或结果。更新异或结果较小的那个即可。
代码
class Solution:
def maximizeXor(self, nums: List[int], queries: List[List[int]]) -> List[int]:
def solve(x, m, s, e):
if nums[0] > m: return -1
max_v = 0
for i in range(31, -1, -1):
if nums[s] & (1<<i) == nums[e] & (1<<i):
max_v += nums[s] & (1<<i)
elif nums[dp[i][e]] <= m and x ^ nums[s] < x ^ nums[e]:
max_v += nums[e] & (1<<i)
# 直接移动较小指针(s)到 dp[i][e],其他不可能是答案
s = dp[i][e]
else:
max_v += nums[s] & (1<<i)
# 直接移动较小指针(e)到 dp[i][e] - 1,其他不可能是答案
e = dp[i][e] - 1
return max_v ^ x
nums.sort()
n = len(nums)
# dp[i][j] 是和 nums[j] 第 i 位相等的最小的数组下标
dp = [[0 for _ in range(n)] for _ in range(32)]
for i in range(32):
for j in range(n):
if j == 0 or (nums[j] & (1<<i)) != (nums[j-1] & (1<<i)): dp[i][j] = j
else: dp[i][j] = dp[i][j-1]
return [solve(x, m, 0, n-1) for x,m in queries]