最近谷歌采访按位操作拼图

时间:2015-10-07 15:35:39

标签: algorithm bitwise-operators bitwise-xor

这是谷歌最近的采访问题:

  

我们将f(X,Y)定义为二进制中不同对应位的数量   X和Y的表示。例如,f(2,7)= 2,因为二进制   2和7的表示分别是010和111。第一个和   第三位不同,所以f(2,7)= 2。

     

给出一组N个正整数,A1,A2,...,AN。求和   f(Ai,Aj)对于所有对(i,j),使得1≤i,j≤N

例如:

  

A = [1,3,5]

     

我们返回

     

f(1,1)+ f(1,3)+ f(1,5)+ f(3,1)+ f(3,3)+ f(3,5)+ f(5,1 )+   f(5,3)+ f(5,5)=

     

0 + 1 + 1 + 1 + 0 + 2 + 1 + 2 + 0 = 8

我能想到这个解决方案是O(n ^ 2)

ListViewItem{ }

我能想到的另一种方法是(考虑到每个元素只包含一个二进制数字):

  • 从数组末尾开始
  • 保持到目前为止的1和0的计数
  • 如果当前元素为1,则它将为最终总和提供int numSetBits(unsigned int A) { int count = 0; while(A != 0) { A = A & (A-1); count++; } return count; } int count_diff_bits(int a, int b) { int x = a ^ b; return numSetBits(x); } for (i = 0; i < n; i++) for (j = 0; j < n; j++) { sum += count_diff_bits(A[i], A[j]); } }
  • 继续这样直到我们到达阵列的开头。

这种方法是否正确。

2 个答案:

答案 0 :(得分:15)

迭代数组,并计算每个位索引中“on”位的数量,例如 [1,3,5]

0 0 1
0 1 1
1 0 1
-----
1 1 3

现在,对于每个位计数器,计算:

  

[位数] * [数组大小 - 位数] * 2

和所有位的总和......

以上示例:

3 * (3 - 3) * 2 = 0
1 * (3 - 1) * 2 = 4
1 * (3 - 1) * 2 = 4
          total = 8

为了说明其工作原理,让我们使用一位来查看问题的一个子集。让我们看看如果我们有一个包含[1, 1, 0, 0, 1, 0, 1]的数组会发生什么。我们的计数是4,大小是7.如果我们检查数组中所有位的第一位(包括self,如问题中所示),我们得到:

  

1 xor 1 = 0
    1 xor 1 = 0
    1 xor 0 = 1
    1 xor 0 = 1
    1 xor 1 = 0
    1 xor 0 = 1
    1 xor 1 = 0

可以看出,该位的贡献是“关闭”位的数量。任何其他“on”位也是如此。我们可以说每个“on”位都算作“off”位的数量:

  

[位数] * [数组大小 - 位数]

乘以2的位置来自哪里?好吧,因为我们对“off”位做同样的事情,除了对于这些,贡献是“on”位的数量:

  

[数组大小 - 位数] * [位数]

当然和上面一样,我们可以相乘......

复杂性是 O(n * k)其中 k 是位数(代码中为32)。

答案 1 :(得分:0)

#include <bits/stdc++.h>
#define MOD 1000000007ll
using namespace std;
typedef long long LL;

int solve(int arr[], int n) {

    int ans = 0;
    // traverse over all bits
    for(int i = 0; i < 31; i++) {

        // count number of elements with ith bit = 0
        long long count = 0;
        for(int j = 0; j < n; j++) if ( ( arr[j] & ( 1 << i ) ) ) count++;

        // add to answer count * (n - count) * 2
        ans += (count * ((LL)n - count) * 2ll) % MOD;
        if(ans >= MOD) ans -= MOD;
    }

    return ans;
}

int main() {

    int arr[] = {1, 3, 5};
    int n = sizeof arr / sizeof arr[0];
    cout << solve(arr, n) << endl; 
    return 0;
}