📜  两个数组中所有对的按位与的总和(1)

📅  最后修改于: 2023-12-03 14:48:52.975000             🧑  作者: Mango

两个数组中所有对的按位与的总和

给定两个长度相同的整数数组nums1和nums2,找到所有对(i, j) 使得 $0 \le i, j < \text{nums1.length}$,并计算nums1[i] and nums2[j]的按位与,然后将所有按位与的结果相加,返回结果。

实现思路

由于要返回所有对的按位与的总和,因此需要先枚举每一个数对(nums1[i], nums2[j]),然后计算它们的按位与值,最后再将所有按位与值相加即可。

具体实现如下:

def total_bitwise_and(nums1: List[int], nums2: List[int]) -> int:
    n = len(nums1)
    res = 0
    for i in range(n):
        for j in range(n):
            res += nums1[i] & nums2[j]
    return res

这是最直接的实现方式,时间复杂度为$O(n^2)$,可能会超时。

另一种更优秀的实现方式是,先找到所有数对的最高公共前缀,然后将公共前缀的值加入结果中。这是因为当两个数按位与时,它们二进制表示中相同位置的两个数按位与的结果要么是0,要么是该位置上的值。

具体实现如下:

def total_bitwise_and(nums1: List[int], nums2: List[int]) -> int:
    n = len(nums1)
    res = 0
    mask = 0x7fffffff  # 为了防止数字溢出,在Python中使用0x7fffffff作为掩码

    while mask > 0:
        has_common_prefix = False
        for i in range(n):
            if nums1[i] & mask != nums2[i] & mask:
                has_common_prefix = False
                break
            else:
                has_common_prefix = True

        if has_common_prefix:
            res += mask & nums1[0]
        mask >>= 1

    return res

这种实现方式的时间复杂度为$O(n \log w)$,其中w是数的位数,在Python中w通常为32位。

示例
assert total_bitwise_and([1, 2, 3], [3, 2, 1]) == 2
总结

本题的难点在于如何避免超时,并且要寻找到最优的解法。通过寻找数对的最高公共前缀可以很好地解决这个问题。不过需要注意的是,在Python中使用二进制掩码时,要考虑数的位数,否则可能会出现数字溢出的问题。