具有给定OR值的对数

时间:2019-03-03 22:21:57

标签: algorithm bit-manipulation

是否可以编写一个函数,该函数接受一个 n 个整数数组和一个整数 k 并返回BITWISE OR值等于的数组元素对数 k 比O( n 2 )时间好吗?

示例:如果我们有一个数组= [21,10,29,8]并且k = 31,则该函数应返回2,因为有效对是(21,10)和(10,29)。 / p>

*为清楚起见*  21 OR 10 = 31,21 OR 29 = 29,21 OR 8 = 29,10 OR 29 = 31,10 OR 8 = 10,29 OR 8 = 29,因此答案为2。

**** k是一个常数,总是31。****

2 个答案:

答案 0 :(得分:5)

假设时间单位是对跨越 k 的单词大小的基本运算,则O( n + k 2 )是可能的:

#include <stdio.h>
#include <stdlib.h>

#define NumberOf(a) (sizeof (a) / sizeof *(a))


static unsigned Count(size_t N, unsigned *A, unsigned k)
{
    //  Count number of elements with each pattern of bits in k.
    unsigned *C = calloc(k + 1, sizeof *C);
    if (!C) exit(EXIT_FAILURE);
    for (size_t n = 0; n < N; ++n)
        if ((A[n] & ~k) == 0) ++C[A[n]];

    //  Count number of solutions formed with different values.
    unsigned T = 0;
    for (size_t i = 0; i < k; ++i)
    for (size_t j = i+1; j <= k; ++j)
        if ((i | j) == k)
            T += C[i] * C[j];

    //  Add solutions formed by same value (only possible when both are k).
    T += C[k] * (C[k]-1) / 2;

    free(C);

    return T;
}


int main(void)
{
    unsigned A[] = { 21, 10, 29, 8 };
    printf("%u\n", Count(NumberOf(A), A, 31));
}

这可以简化为O( n + p 2 ),其中 p 是通过将每个数组元素压缩为刚好在 k 中设置的位(删除不在 k 中的位并将其余位移动为连续)。另外,可以改善计算组合的主循环,但我认为这不会影响O()时间。

答案 1 :(得分:1)

人们认为答案是“否”。

假设您的k2^s - 1(因此它是二进制的111...111),并且所有数字最多为k。然后

a or b = k <=> (~a) and (~b) = 0.

,其中~是“按位不”。例如

110 or 101 = 111 <=> 001 and 010 = 0

这是一个一般的正交向量问题(OVP),流行的猜想指出,它的求解速度不及O(n^2)(我忽略了一些细节)。

请参见此处的猜想1:https://arxiv.org/pdf/1510.02824.pdf