📌  相关文章
📜  计算来自其AND和XOR之和等于K的两倍的数组中的对(1)

📅  最后修改于: 2023-12-03 15:12:04.342000             🧑  作者: Mango

题目介绍

给定一个长度为N的整数数组nums以及一个整数K,找到满足下列条件的不同二元组(i, j)的数量:

  1. 0 <= i < j < N
  2. (nums[i] AND nums[j]) + (nums[i] XOR nums[j]) = 2 * K

其中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。