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

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

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

问题描述

给定两个长度相同的数组,计算这两个数组中所有对的按位与的总和。例如,给定数组 arr1 = [1, 2, 3] 和数组 arr2 = [2, 3, 4],它们中所有对的按位与分别为 1&2=01&3=11&4=02&2=22&3=22&4=03&2=23&3=33&4=0,其总和为 0+1+0+2+2+0+2+3+0=10

解题思路

对于每一位上都有“与运算规则”,即两个数在相同位置上的数都为1时结果为1,否则结果为0。所以对于两个数组中每一个数,我们可以用二进制的方式将它们拆开,然后两两按位与。

注意到,无论两个数在某个特定位置上的数相不相同,在这个位置上的结果最多也就只有0或者1两种可能,而且这个位置的值只能是1或者0,所以我们可以用一个长度为32的数组 bitcount 来维护所有位置上1的个数,这个数组的初始化为0。

对于每一个数,我们将它与 bitcount 进行按位与,然后在 bitcount 上对应的位置上加上这个数在这个位置上的值。

最后,对于任意两个数组中的数 arr1[i]arr2[j],它们的对应位置的按位与结果即为 arr1[i] & arr2[j],将结果加到答案中。

代码实现
class Solution:
    def countAndSum(self, arr1: List[int], arr2: List[int]) -> int:
        n = len(arr1)
        bitcount = [0] * 32
        for i in range(n):
            num = arr1[i]
            for j in range(32):
                bitcount[j] += num & 1
                num >>= 1
        ans = 0
        for i in range(n):
            num = arr2[i]
            tmp = 0
            for j in range(32):
                if num & (1 << j):
                    tmp += bitcount[j] * (1 << j)
            ans += tmp
        return ans
复杂度分析

该算法时间复杂度为 $O(32n)=O(n)$,其中 $n$ 为数组的长度。空间复杂度为 $O(32)=O(1)$,只需要一个长度为32的数组来维护每个位置上1的个数。