📅  最后修改于: 2023-12-03 15:39:40.134000             🧑  作者: Mango
在这个问题中,给定一个正整数数组 nums,我们需要找到所有子数组的按位与之和。
给定一个正整数数组 nums,它包含 n 个不同的元素,其中每个元素 nums[i] 的值都是非负整数。找到所有子数组的按位与之和。
一种直观的解法是暴力枚举所有子数组,然后对每个子数组进行按位与操作,最后求和。但是,这个做法的时间复杂度达到了 O(n^3),因此不适用于该问题。
更优秀的解法是:我们可以依次枚举每一位,考虑在该位上,所有数的按位与之和是多少。我们可以发现,如果对于某一位,存在一个数 k,它在该位上的值为 0,那么所有在这一位上值为 1 的数的按位与之和肯定也为 0。因此,我们只需要找到那些在该位上的值都为 1 的数,然后进行按位与操作即可。
我们可以使用两个指针 left 和 right,它们分别表示当前考虑的子数组的左右端点。对于每个 left,我们让 right 向右移动,直到所有数在当前位上的值都为 1,然后计算当前子数组按位与之和,最后将右指针 right 移回 left 的位置。
这样,我们就可以得到所有子数组的按位与之和。
具体的代码实现如下所示:
def sum_of_bitwise_and(nums: List[int]) -> int:
res = 0
n = len(nums)
for i in range(30):
left, right = 0, 0
mask = 1 << i
while right < n:
if nums[right] & mask:
right += 1
else:
res += (right - left) * (right - left + 1) // 2 * mask
left = right + 1
right = left
if left < n:
res += (n - left) * (n - left + 1) // 2 * mask
return res
其中,我们使用了位运算和数学公式相结合的方法,让代码更加简洁明了。具体来说:
这个问题可以使用位运算和双指针的方法解决。我们需要依次枚举每一位,然后对于每一位,使用双指针分别表示当前考虑的子数组的左右端点,统计所有子数组在当前位上的按位与之和。时间复杂度为 O(nlogC),其中 C 表示数组中所有数的最大值。