所有对中的比特差异总和

时间:2016-09-01 23:44:19

标签: arrays algorithm bit-manipulation

问题陈述如下:

给定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位移位将在相同的时钟周期内发生(或者与线性迭代相比相对较快),整体运行时间将由线性迭代控制在阵列上。

这是正确的解释吗?

2 个答案:

答案 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