📅  最后修改于: 2023-12-03 14:55:20.468000             🧑  作者: Mango
给定一个非空且仅包含正整数的数组nums和一个正整数k,找出一个数m使得minimize(nums[i] XOR m) for i in range(len(nums))),同时满足m XOR k <= m,其中XOR表示按位异或运算符。
一个简单的解法是对于每个数m,计算其与所有nums[i]的异或值,找到其中的最小值,最后比较m XOR k与m的大小关系,确定答案是否合法。时间复杂度为O(n^2),对于数据规模较小的情况可以接受。
稍微优化一下暴力枚举的做法,可以通过记录nums数组中的所有数的二进制位构成的Trie树,简化每个数与nums[i]异或的计算。具体来说,对于每个数num,将其从高到低的二进制位插入到Trie树中,同时记录对应的终端节点的路径(0表示当前位为0,1表示为1),表示num对应为止的异或结果。对于每个m,则按照Trie树的规则,从高到低遍历所有对应的位,根据异或结果是否为1,在Trie树中选择相应方向的子节点进行遍历,在到达终端节点时,即可得到m与num异或的结果,从而比较得到最小值。时间复杂度为O(nlogm),其中m为数组nums中最大数的二进制位数。
利用异或的性质x XOR y = z => x XOR z = y,可知对于任意的m和num,有m XOR num XOR num = m。因此,将所有的nums[i]插入到一个Trie树中,然后从高到低遍历所有的m的二进制位,对于每一位,选择让异或结果为0的方向(即num的当前位为m的当前位的取反),如果不存在这样的方向,就只能选择异或结果为1的方向。这个过程可以通过记录Trie树中0和1方向的节点个数来实现。代码如下:
class Solution:
def __init__(self):
self.trie = {}
self.max_bit = 31 # 假设最大数只有31位
self.nodes = [[0, 0] for _ in range(self.max_bit + 1)]
def findMaximumXOR(self, nums: List[int], k: int) -> int:
for num in nums:
node = self.trie
for i in range(self.max_bit, -1, -1):
bit = (num >> i) & 1
if bit not in node:
node[bit] = {}
node = node[bit]
max_xor = 0
for num in nums:
node = self.trie
xor = 0
for i in range(self.max_bit, -1, -1):
bit = (num >> i) & 1
if self.nodes[i][bit ^ 1] > 0:
node = node[bit ^ 1]
xor += (1 << i)
else:
node = node[bit]
max_xor = max(max_xor, xor)
if k != 0:
node = self.trie
xor = 0
for i in range(self.max_bit, -1, -1):
bit = (k >> i) & 1
if self.nodes[i][bit] > 0:
node = node[bit]
xor += (bit << i)
else:
node = node[bit ^ 1]
xor += ((bit ^ 1) << i)
if xor ^ k <= xor:
max_xor = max(max_xor, xor ^ k)
return max_xor