📅  最后修改于: 2023-12-03 15:21:40.901000             🧑  作者: Mango
二进制数组是一个只包含 0 和 1 的数组。给定一个长度为 n 的二进制数组 nums,我们可以形成 n(n-1)/2 对数字。对于每个数字对 (nums[i], nums[j]),我们可以计算它们的乘积 nums[i]*nums[j]。请计算所有数字对的乘积总和。
暴力枚举法非常简单。我们可以使用双重循环枚举所有数字对,对每对数字计算乘积并累加到结果中。时间复杂度为 $O(n^2)$,空间复杂度为 $O(1)$。
class Solution {
public:
int binaryArrayMultiplication(vector<int>& nums) {
int ans = 0;
for (int i = 0; i < nums.size(); i++) {
for (int j = i + 1; j < nums.size(); j++) {
ans += nums[i] * nums[j];
}
}
return ans;
}
};
这是一种非常巧妙的方法,利用位运算进行优化。我们可以枚举二进制数的每一位,统计该位上 1 的个数和 0 的个数,然后将它们相乘,得到该位上贡献的乘积。最后将所有位上的乘积累加即可。时间复杂度为 $O(n\log{W})$,其中 $W$ 是数值的位数,空间复杂度为 $O(1)$。
class Solution {
public:
int binaryArrayMultiplication(vector<int>& nums) {
int ans = 0;
int n = nums.size();
for (int i = 0; i < 32; i++) {
int cnt1 = 0, cnt0 = 0;
for (int j = 0; j < n; j++) {
if (nums[j] & (1 << i)) cnt1++;
else cnt0++;
}
ans += cnt1 * cnt0 * (1 << i);
}
return ans;
}
};
本题通过暴力枚举和位运算两种方法进行解决,位运算的方法可以将时间复杂度从 $O(n^2)$ 降至 $O(n\log{W})$,是一种非常巧妙的优化手段。