📅  最后修改于: 2023-12-03 15:41:36.512000             🧑  作者: Mango
对于一个整数数组,定义“对”为数组中的任意两个不同下标的元素。找到数组中所有“对”,使得它们的按位 AND 和按位 XOR 的结果之和等于给定的整数 K。例如,数组 [1, 2, 3, 4, 5],K = 7,有两个满足要求的“对”:[1, 3] 和 [2, 5]。
考虑如何计算两个数的按位 AND 和按位 XOR。对于两个二进制数,它们在某一位上的 AND 和 XOR 的结果分别为:
这启示我们考虑对整个数组进行位运算,而不是每对数字单独计算。
具体来说,计算所有数字的按位 AND 和按位 XOR 的结果,并将位运算结果分别存储在两个数组中。然后遍历所有“对”,将它们的按位 AND 和按位 XOR 的结果之和进行累加,最后判断是否等于给定的整数 K。
在计算两个数字的按位 AND 时,如果两个数字的某一位都为 0,则它们的按位 AND 的结果必然也为 0。因此,在计算按位 AND 时,我们可以跳过一些数字,以减少计算量。
在计算两个数字的按位 XOR 时,如果两个数字的某一位不同,则它们的按位 XOR 的结果为 1。因此,在计算按位 XOR 时,我们可以记录两个数字在某一位上的差异情况,并统计不同情况的个数。这可以通过使用哈希表来实现。
时间复杂度为 O(n),其中 n 为数组长度。
from collections import defaultdict
def count_pairs(arr, k):
bit_count = [defaultdict(int) for _ in range(32)]
for num in arr:
for i in range(32):
bit_count[i][(num >> i) & 1] += 1
result = 0
for num in arr:
and_sum = 0
xor_sum = 0
for i in range(32):
bit = (num >> i) & 1
and_sum += bit_count[i][1] * bit
xor_sum += bit_count[i][1] * bit if ((k >> i) & 1) == 1 else bit_count[i][0] * bit
result += and_sum * ((k ^ num) ^ num)
result += xor_sum * ((k & num) ^ num)
return result // 2
代码中使用了一个长度为 32 的列表 bit_count
来记录所有数字在每一位上的出现次数。其中,bit_count[i][0]
表示所有数字在第 i 位上为 0 的个数,bit_count[i][1]
表示所有数字在第 i 位上为 1 的个数。
然后遍历数组中的每个数字 num,并计算出它和其他数字的按位 AND 和按位 XOR 的结果。具体来说,对于每一位 i,如果 num 在该位上为 0,那么它与其他数字的按位 AND 的结果必然为 0,因此我们可以跳过这些数字;否则,我们需要计算其中所有数字在该位上为 1 的个数,并将其累加到按位 AND 的结果中。对于按位 XOR,我们可以统计所有数字在该位上与 k 的差异情况,并分别计算它们的个数。具体来说,如果 num 在该位上为 1,那么我们需要统计所有与 num 不同的数字在该位上为 1 的个数,以及所有与 num 相同的数字在该位上为 0 的个数;否则,我们需要统计所有与 num 不同的数字在该位上为 0 的个数,以及所有与 num 相同的数字在该位上为 1 的个数。
最后,将所有“对”的按位 AND 和按位 XOR 的结果之和进行累加,并返回结果除以 2,即可得到答案。