📅  最后修改于: 2023-12-03 15:12:04.342000             🧑  作者: Mango
给定一个长度为N的整数数组nums以及一个整数K,找到满足下列条件的不同二元组(i, j)的数量:
其中AND表示按位与运算,XOR表示按位异或运算。
我们可以枚举所有的二元组(i, j),然后判断是否满足条件,并记录满足条件的二元组数目。但是,这种暴力枚举的时间复杂度是O(N^2),不能满足题目要求,因此需要优化算法。
首先,根据位运算的性质,我们知道,nums[i] AND nums[j] <= nums[i],nums[i] AND nums[j] <= nums[j],因此可以将AND和XOR拆开来看。
将原式拆开:
(nums[i] AND nums[j]) + (nums[i] XOR nums[j]) = 2 * K
等价于:
nums[i] AND nums[j] = 2 * K - nums[i] XOR nums[j]
接下来,我们可以枚举i,然后根据上式计算nums[i] AND nums[j]的值,设该值为x,如果x <= nums[i],则说明满足条件,此时可以用哈希表记录x出现的次数,然后枚举j,计算nums[i] XOR nums[j]的值,设该值为y,如果2 * K - y的值在哈希表中出现过,则说明满足条件,此时将x出现的次数乘上2 * K - y出现的次数,并累加到最终答案中。
这种时间复杂度为O(N)的算法可以通过该题。
def count_pairs(nums, K):
cnt = 0
xor_cnt = collections.defaultdict(int)
for i in range(len(nums)):
x = nums[i] & (-nums[i])
if x <= nums[i] and 2 * K - nums[i] in xor_cnt:
cnt += xor_cnt[2 * K - nums[i]]
xor_cnt[xor_cnt ^ nums[i]] += 1
return cnt
需要注意的是,为了找到nums[i]的二进制表示中最低位的1,我们可以使用x = nums[i] & (-nums[i])这个小技巧,其实就是将最低位的1保留,其余位置为0。