📌  相关文章
📜  两个数组中所有可能对的按位与的总和(1)

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

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

题目描述

给定两个长度相同的非负整数数组,找到所有可能的对,使得每对中的两个数的按位与值的总和最大。

示例
输入: nums1 = [4,5,7], nums2 = [3,6,9]
输出: 12
解释: 可能的对为:
(4, 6), (4, 9), (5, 6), (5, 9), (7, 6), (7, 9)
其对应的按位与值分别为:
4 & 6 = 4
4 & 9 = 0
5 & 6 = 4
5 & 9 = 1
7 & 6 = 6
7 & 9 = 1
因此,最大的按位与值为 4 + 0 + 4 + 1 + 6 + 1 = 12。
解题思路
  1. 遍历所有可能的对,计算它们按位与的值,然后求和。
  2. 通过位运算优化求和过程:
    1. 如果两个数的最高位都是 1,则它们的按位与的值一定大于等于 2^(n-1),其中 n 是这两个数的二进制位数。
    2. 如果两个数中有一个数的某一个二进制位是 0,则这一位的按位与的值一定是 0。
    3. 所以,我们只需要比较两个数的最高位是否都是 1,如果是,则它们的按位与的值一定大于等于 2^(n-1),其中 n 是这两个数的二进制位数;否则,找到第一个不相等的位,该位之前的按位与的值一定为 0。
代码实现
def total_bitwise_and(nums1, nums2):
    # 计算 nums1 和 nums2 中所有可能对的按位与的值之和
    res = 0
    for i in range(len(nums1)):
        for j in range(len(nums2)):
            # 计算按位与的值
            bitwise_and = nums1[i] & nums2[j]
            res += bitwise_and
    return res

def total_bitwise_and_optimized(nums1, nums2):
    # 计算 nums1 和 nums2 中所有可能对的按位与的值之和(位运算优化)
    res = 0
    n = len(nums1)
    for bit in range(31, -1, -1):
        # 统计 nums1 和 nums2 中第 bit 位都是 1 的数的个数
        cnt = 0
        for i in range(n):
            if nums1[i] & (1 << bit) and nums2[i] & (1 << bit):
                cnt += 1
        # 如果 cnt > 0,则这些数的第 bit 位的按位与的值一定大于等于 2^(bit-1)
        if cnt > 0:
            res += (1 << bit-1) * cnt
        else:
            # 找到第一个不相等的位,该位之前的按位与的值一定为 0
            for i in range(n):
                if nums1[i] & (1 << bit) != nums2[i] & (1 << bit):
                    break
            else:
                continue
            # nums1 和 nums2 中第 i 个数之前的按位与的值一定为 0
            res += (1 << bit-1) * i
    return res
复杂度分析
时间复杂度
  • total_bitwise_and 的时间复杂度是 O(n^2),其中 n 是 nums1 和 nums2 的长度。
  • total_bitwise_and_optimized 的时间复杂度是 O(32n),即 O(n),其中 n 是 nums1 和 nums2 的长度。
空间复杂度
  • total_bitwise_and 的空间复杂度是 O(1)。
  • total_bitwise_and_optimized 的空间复杂度是 O(1)。