问题陈述如下:
给定n个整数的整数数组,找到可以从数组元素形成的所有对中的位差之和。一对(x,y)的比特差是x和y的二进制表示中相同位置处的不同比特的计数。 例如,2和7的位差为2. 2的二进制表示为010,7为111(第一位和最后一位在两个数字上不同)。
示例:
Input: arr[] = {1, 2}
Output: 4
All pairs in array are (1, 1), (1, 2)
(2, 1), (2, 2)
Sum of bit differences = 0 + 2 +
2 + 0
= 4
基于this post,最有效(O(n))解决方案的运行时间如下:
这个想法是计算各个位位置的差异。我们从0到31遍历,并按位设置计数。让这个计数'计数'。如果没有设置,会有“n计数”数字。因此,第i位的差异计数将是“count *(n-count)* 2”。
// C++ program to compute sum of pairwise bit differences
#include <bits/stdc++.h>
using namespace std;
int sumBitDifferences(int arr[], int n)
{
int ans = 0; // Initialize result
// traverse over all bits
for (int i = 0; i < 32; i++)
{
// count number of elements with i'th bit set
int count = 0;
for (int j = 0; j < n; j++)
if ( (arr[j] & (1 << i)) )
count++;
// Add "count * (n - count) * 2" to the answer
ans += (count * (n - count) * 2);
}
return ans;
}
// Driver prorgram
int main()
{
int arr[] = {1, 3, 5};
int n = sizeof arr / sizeof arr[0];
cout << sumBitDifferences(arr, n) << endl;
return 0;
}
我还不完全清楚的是,当每次迭代有两个for循环递增1时,运行时间是如何线性的。我解释它的方式是,因为外部循环从0迭代到32 (对应于每个数字的第0和第32位)并且因为我猜测所有32位移位将在相同的时钟周期内发生(或者与线性迭代相比相对较快),整体运行时间将由线性迭代控制在阵列上。
这是正确的解释吗?
答案 0 :(得分:4)
在英语中,&#34;我的算法在O(n)时间运行&#34;转换为&#34;对于非常大的输入,我的算法在时间上与n
成比例地运行&#34;。比例方面的原因是外循环中的32次迭代不会产生任何差异。执行时间仍然与n成正比。
让我们看一个不同的例子:
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
// do something
}
}
在此示例中,执行时间与n 2 成比例,因此它不 O(n)。然而,它是O(n 2 )。技术上O(n 3 )和O(n 4 ),......也是如此。这是从定义中得出的。
只有这么多,你可以用英语谈论这些东西而不会有误解,所以如果你想要明确这些概念,你最好在介绍算法教科书或在线检查正式定义。上课并制定一些例子。
答案 1 :(得分:0)
我们不必比较两个数字,而是可以相互比较每个数字的第i_bit,这将使您的时间复杂度从O(n * n)降低到O(32 * n),我们只需要计算零和一个可能在每个数字的第i_th位。 简单的Cpp实现看起来像这样:
foo
任何对此逻辑感到困惑的人都可以参考以下说明:https://www.youtube.com/watch?v=OKROwC2fLEg