是否有算法在线性时间复杂度中找到按位OR或数组?
假设数组是{1,2,3},那么所有对的总和id 1 | 2 + 2 | 3 + 1 | 3 = 9。
我可以使用以下算法在O(n)中找到所有对AND和....如何更改此以获得所有对OR和。
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 k = 0; // Initialize the count
for (int j = 0; j < n; j++)
if ( (arr[j] & (1 << i)) )
k++;
// There are k set bits, means k(k-1)/2 pairs.
// Every pair adds 2^i to the answer. Therefore,
// we add "2^i * [k*(k-1)/2]" to the answer.
ans += (1<<i) * (k*(k-1)/2);
}
从这里开始:http://www.geeksforgeeks.org/calculate-sum-of-bitwise-and-of-all-pairs/
答案 0 :(得分:4)
你可以在线性时间内完成。这个想法如下:
对于每个数字,通过单独查看每个位并使用缓存的总和来计算数字的按位OR与数组中所有其他数字的总和。例如,考虑总和1 | 1 + 1 | 2 + 1 | 3 = 1 + 3 + 3 = 7.
因为1的最后一位是1,所以按位或1的结果将最后一位设置为1.因此,所有三个数字1 | 1,1 | 2和1 | 3将具有最后一位等于1.其中两个数字的两位设置为1,这正是将两位设置为1的元素数。通过将这些位分组,我们可以得到总和3 * 1(三位) )+ 2 * 2(两个两位)= 7.
对每个元素重复此过程可以计算数组中所有有序元素对的所有按位ors的总和。所以在你的例子中,将计算1 | 2和2 | 1,1 | 1也是如此。所以你必须减去像1 | 1这样的所有情况,然后除以2来计算重复计算。
让我们试试这个算法。
以二进制编写数字,{1,2,3} = {01,10,11}。一个位设置有2个数字,2个位设置为2个。
对于01,我们得到3 * 1 + 2 * 2 = 7的总和。
该算法为O(任何数组元素中n *最大位数)。
编辑:我们可以通过简单地从所有对中减去所有0-0对的计数来修改您的发布算法,以获得每个位位置的所有0-1或1-1对。像这样:
int ans = 0; // Initialize result
// Traverse over all bits
for (int i = 0; i < 32; i++)
{
// Count number of elements with i'th bit not set
int k = 0; // Initialize the count
for (int j = 0; j < n; j++)
if ( !(arr[j] & (1 << i)) )
k++;
// There are k not set bits, means k(k-1)/2 pairs that don't contribute to the total sum, out of n*(n-1)/2 pairs.
// So we subtract the ones from don't contribute from the ones that do.
ans += (1<<i) * (n*(n-1)/2 - k*(k-1)/2);
}