二进制代码上的约束计数集

时间:2018-05-30 03:30:57

标签: java algorithm binary

问题公式:给定长度为l的二进制代码,对于每t位设置(l%t = 0),如果存在至少一位值1,我们将1加到结果中。

我的问题:如何有效地获得最终结果?

例如,我们有二进制代码010 110 000,并且t = 3。然后最终的结果是2.因为对于000,没有值为1.对于110,至少存在一个值为1.我们在结果中加1。对于010,还存在一位值1.我们在结果中加1。因此,最终结果是2。

我的问题是如何在不扫描每个t位的情况下有效地解决这个问题,这会导致时间复杂度与二进制代码的长度呈线性关系。

对于计数集问题(计算二进制代码中有多少1),有些算法通过采用有限数量的掩码和移位操作(例如MIT HAKMEM Count算法)来获取恒定时间来解决它。

但是,传统计数集问题的现有算法不能用于解决我的问题。

有谁知道我的问题的一些技巧?如果使问题更容易解决,您可以假设输入二进制代码的最大长度。

1 个答案:

答案 0 :(得分:2)

来自comment

  

然后你可以假设输入是这个问题的64位整数的二进制代码。

以下是两种不同的方法。

第一次在 O(I / t)中运行,并通过测试所有0位的每一组来工作。

public static int countSets(int setSize, long bits) {
    Long mask = (1L << setSize) - 1;
    int count = 0;
    for (long b = bits; b != 0; b >>>= setSize)
        if ((b & mask) != 0)
            count++;
    return count;
}

第二次在 O(log I)中运行,并将一组的位折叠到该组的最右位,然后计算设置的位数。

public static int countSets(int setSize, int bitCount, long bits) {
    long b = bits, mask = 1;
    for (int i = 1; i < setSize; i++)
        b |= bits >>> i;
    for (int i = setSize; i < bitCount; i <<= 1)
        mask |= mask << i;
    return Long.bitCount(b & mask);
}

进一步说明

第一种方法为集合构建掩码,例如使用t = 3时,掩码为111

然后将值一次性移位到右侧t位,例如使用input = 010 110 000t = 3,您可以获得:

mask = 111
b = 010 110 000  ->  b & mask = 000  ->  don't count
b =     010 110  ->  b & mask = 110  ->  count
b =         010  ->  b & mask = 010  ->  count
result: 2

第二种方法首先将位合并到集合的最右位,例如,使用input = 010 110 000t = 3,您可以获得:

bits      = 010 110 000
bits >> 1 = 001 011 000
bits >> 2 = 000 101 100
b (OR'd)  = 011 111 100

然后构建一个掩码,仅检查最右边的位,然后应用掩码并对设置的位进行计数:

mask     = 001 001 001
b & mask = 001 001 000
result: 2