我们有一个数组A (say [1,2,3])
。我们需要找到数组中所有整数对的 XOR(^)SUM 。
虽然这可以在O(n^2)
中轻松完成,但我如何才能提高解决方案的复杂性?
例如,对于上面的数组A,答案是(1^2)+(1^3)+(2^3) = 6
谢谢。
答案 0 :(得分:20)
您可以将计算分开,一次执行一位。
例如,查看数组中所有数字的最右边位。假设a
个数字最右边有0位,b
个数字有1位数。然后在这些对中,a*b
将在XOR的最右边位置有1个。这是因为有a*b
种方法可以选择一个具有0位且一个具有1位的数字。因此,这些位将对所有XOR的总和贡献a*b
。
通常,当查看n
位(最右边的位是第0位)时,计算有多少个数为0(称为 n ),有多少1(称之为b n )。对最终总和的贡献将是 n * b n * 2 n 。您需要为每个位执行此操作并将所有这些贡献加起来。
这可以在O(kn)时间内完成,其中k
是给定值中的位数。
答案 1 :(得分:1)
这是一个jsFiddle确认interjay的答案,它使用O(N ^ 2)和O(Nk)两种方法进行计算:
var list = [1,2,2,3,4,5]
function xorsum_on2( a )
{
var sum = 0
for( var i=0 ; i<a.length ; ++i )
for( var j=i+1 ; j<a.length ; ++j )
sum += a[i]^a[j]
return sum
}
// This sets all elements of a to 0
function xorsum_onk( a )
{
var allzeroes;
var sum = 0;
var power = 0;
do {
allzeroes = true;
var bitcount = [0,0];
for( var i=0 ; i<a.length ; ++i )
{
bitcount[a[i]&1]++;
a[i] >>= 1;
if( a[i] ) allzeroes = false;
}
sum += (bitcount[0]*bitcount[1]) << power++;
} while( !allzeroes );
return sum;
}
var onk = document.getElementById("onk")
var on2 = document.getElementById("on2")
on2.innerHTML = xorsum_on2(list)
onk.innerHTML = xorsum_onk(list)
答案 2 :(得分:0)
#include <iostream>
using namespace std;
int main() {
long long int n,i,j,k;
cin>>n; // number of elements in array
long long int arr[n],ans=0;
for(i=0;i<n;i++)
cin>>arr[i];
// iterate through all the bits
for(i=0;i<32;i++)
{
k=0; // k is the number of set bits in the array at ith psotion
for(j=0;j<n;j++)
if((arr[j] & (1<<i)))
k++;
/* there are k set bits and n-k unset bits.
therefore number of pairs with one set bit and one unset bit is kC1 and n-kC1
Every pair adds 2^i in the answer.
*/
ans+= (1<<i)*(k*(n-k));
}
cout<<ans<<endl;
return 0;
}