📅  最后修改于: 2023-12-03 15:27:35.271000             🧑  作者: Mango
有一个长度为 $n$ 的非空数组,其中有 $a_0, a_1, ..., a_{n-1}$ 。
定义所有对 $(i, j)$ 的按位与(bitwise AND)之和为:
$$ \sum\limits_{0 \leq i < j < n} a_i \operatorname{and} a_j $$
其中 $\operatorname{and}$ 表示按位与运算。
你可以在数组的任意位置插入任意整数,以最大化对按位与之和的求和。
请编写一个函数,该函数接受一个整数数组,返回数组中所有对的按位与之和。
因为要求对数组中的所有数按位与的和,所以我们需要让所有数的二进制的每一位都尽量都为 1,这样才能保证按位与的结果尽可能的大。
我们看最高位(首位)怎么计算:
假设数组中所有数二进制的最高位相同。将它们的最高位和次高位取出来比较,如果都是1,那么组成的数就是2。
如果有一个不是1,那么组成的数只能是1。
下面的例子比较简单,只是为了说明问题:
0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 0
最高位都是0,从低位开始比较,发现第6位,4个数中只有第3个数该位是1,所以最高位的值为 1; 前6位都是1组成的二进制数为 001000,转为十进制数为8。
计算次高位:
重复上面的步骤,最后组成的二进制数为 001001。
以此类推,直至最后一位。
得到数组中所有数按位与结果的和。
class Solution:
def rangeBitwiseAnd(self, nums: List[int]) -> int:
if not nums:
return 0
res, mask = 0, 1 << 30
while mask > 0 and (nums[0] & mask) == 0:
mask >>= 1
while mask > 0:
prev_bit = nums[0] & mask
for n in nums[1:]:
if (n & mask) != prev_bit:
mask >>= 1
return res
res += mask
mask >>= 1
return res
代码中,我们仅需要对每个数字最大值的一位进行循环计算,如果当前值同时出现在当前位最大的两个数字中,那么就同时给结果加上该二进制位对应的数值。