【问题标题】:Suitable data structure to store and query integers based on most significant bits基于最高有效位存储和查询整数的合适数据结构
【发布时间】:2017-03-16 09:06:58
【问题描述】:

鉴于 N 64 位无符号整数,我希望将它们有效地存储在数据结构 D 中并能够执行以下查询:

给定一个整数 A,返回 D 中至少有 k 个最高有效位相同的所有整数。

例如,如果有一个包含 3 个 64 位整数的列表:

a. 1010010000000000010000000000000000000000100000000000000000000001
b. 0000000100001000000000010000000000000000000000000000000000000001
c. 1010010100000000000000010000000000000000000000000000000000000001

查询 A 是:

1010010000000000000000010000000000000000000000000000000000000001

我们选择 k = 7

它应该返回一个包含 2 个元素的列表:

a.1010010000000000010000000000000000000000100000000000000000000001
c.1010010100000000000000010000000000000000000000000000000000000001

如果查询 A1 是:

0010010000000000000000010000000000000000000000000000000000000001

和 k = 2

它应该返回一个元素的列表:

b. 0000000100001000000000010000000000000000000000000000000000000001

如果查询 A2 是:

1110010000000000000000010000000000000000000000000000000000000001

和 k = 3

它应该返回一个空列表。

N 大小应为 5000 万个整数。

你能指出最合适的数据结构吗? 如果我可以从数据结构 D 中插入/删除,那就太好了 创建之后。

【问题讨论】:

    标签: algorithm data-structures tree hashmap trie


    【解决方案1】:

    如果您将整数视为从最高有效位开始的位串,则可以使用bitwise trietrie 允许您存储键值对,尽管在您的情况下您实际上不需要存储与每个整数关联的值,但它还允许有效搜索以给定前缀开头的所有条目(即以给定的 k 个最高有效位)。另一种选择是Y-fast trie

    【讨论】:

    • 也许 Judy 数组可以工作 (judy.sourceforge.net)。你知道任何 y-fast trie 纯 c++ 实现吗?因为我看到了 Judy 数组 API,看起来很困惑
    • 我找到了this 的实现,但我没有使用它。
    【解决方案2】:

    使用特里:

    定义一个trie-nodetrie

    struct node{
       node *zero;
       node *one;
       vector <char> index; //Stores the indexes of the numbers which possess such bit pattern
    }
    

    零初始化trieroot

    node *root = new node;
    root->zero = nullptr;
    root->one  = nullptr;
    

    遵循与二叉树相同的插入技术,从上到下递归。

    处理完第一位后,trie 将如下所示:

                  root
    
              /          \
    
       0{np, np, {b}}    1{np, np, {a, c}}
    

    处理完第 2 位后,trie 将如下所示:

                  root
    
              /          \
    
       0{np, np, {b}}    1{np, np, {a, c}}
                            /
        /                   
    00{np, np, {b}}   10{np, np, {a,c}} 
    

    这个trie中的搜索方法与二叉搜索树相同,每个查询的复杂度O(k)

    k &lt;= 64.


    另一种解决方案:简单高效地处理大量查询

    在给定的整数列表中,不同的对可以有不同的位模式,大小为k 位。例如,4 大小可以有不同的位模式k=2,每个位模式可以有自己的数字列表。

    为了保证查询的快速处理,我们可以使用std::unordered_mapstd::vector

    vector<unordered_map<int, vector<char>>> vecMapForEachBitPos(64);  // for 64-bit integers.
    

    获取每个数字的第一位 (MSB),将 bitPattern 值作为 key 放入 unordered_map 并将数字索引(在您的情况下为 a./b./c.)作为值。

    对第 2 个 MSB、第 3 个 MSB……重复上述步骤,直到第 64 个 MSB 得到如下结果:

    v[0] = {{0, b}, {1, {a, c}}};
    
    v[1] = {{0, b}, {2, {a, c}}};
    
    v[2] = {{0, b}, {5, {a, c}}};
      ^      ^  ^    ^   ^  ^
      |      |  |    |   |  |
      Bit    |  -----|----------Number index having such bit pattern.
    Position |       |
              ----------value of bitpattern till that bit position.
    

    在这之后你的问题就变得很简单了。

    v[k-1].find(A &gt;&gt; (64-k)).second 存储您要查找的列表。如果v[k-1].find(A &gt;&gt; (64-k)) == v[k-1].end(),没有数字满足位模式,则返回一个空列表作为解决方案。

    搜索复杂度:每个查询O(1)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-08
      • 1970-01-01
      • 2010-12-29
      • 1970-01-01
      • 1970-01-01
      • 2010-10-09
      • 2018-07-18
      相关资源
      最近更新 更多