有人可以建议使用更快的算法来识别大型二进制数据中1的连续范围吗?

遍历数据是唯一的解决方案吗?在最不希望的情况下,遍历会给出O(n),我真的不想要。

有谁可以建议更快的算法?

如下图所示。我需要找到索引4000,它是1的连续范围的起始位置

index 0
|
00000000000000000000000000000000000000000011111100000

最佳答案

我想不出什么都不是O(n),因为数据始终是未排序的。

但是,我可以想到快捷方式,因为您需要至少3个一组,并且是二进制数据。

#include <iostream>

using namespace std;

int main()
{
    unsigned int seed = 3758096384; //11100000000000000000000000000000
    unsigned int testvar = 419307644; //00011000111111100010000001111100
    int result = 0;
    int continuous = 0;

    while (seed != 7 && (continuous == 1 || result == 0)) {
        if (seed == (testvar & seed)) {
            result |= seed;
            continuous = 1;
        } else
            continuous = 0;
        seed >>= 1;
    }
    // result = 16646144 or 00000000111111100000000000000000
    cout << result << endl;
    //the index, 8388608 or 00000000100000000000000000000000
    cout << (int)((result ^ (result >> 1)) & ~(result >> 1)) << endl;
    return 0;
}

怎么运行的:
它是一个二进制滤波器,它创建3位掩码,并在循环的每一步中向左连续移1。

因此,您将这些数字用作过滤器:
3758096384 - 11100000000000000000000000000000
1879048192 - 01110000000000000000000000000000
939524096  - 00111000000000000000000000000000
...
14         - 00000000000000000000000000001110
7          - 00000000000000000000000000000111

然后,它检查种子是否与测试的数字和种子本身之间的逻辑与结果相符(这将过滤所有与过滤器不匹配的数字)。

如果种子和AND匹配,它将使用逻辑“或”将种子移到结果,并设置一个continuous以控制序列的连续性。第一次结果不连续时,它将中断循环。

最后,您将得到结果并可以通过以下方式计算索引:
1110
0111 SHIFT TO LEFT by 1 and XOR
1001
0111 NOT (SHIFT TO LEFT by 1) and AND
------------
1000

您将需要按32位块扫描50gb数据(很容易适应64位,甚至对其进行 vector 化处理)。

10-08 08:55
查看更多