【问题标题】:What is the fastest way to return x,y coordinates that are present in both list A and list B?返回列表 A 和列表 B 中都存在的 x,y 坐标的最快方法是什么?
【发布时间】:2011-03-24 16:48:12
【问题描述】:

我有两个 x,y 坐标列表(列表 A 和列表 B),其中 0

我一直在考虑将列表表示为两个位网格并按位和可能?

列表 A 大约有 1000 个条目,并且可能每 10,000 个请求更改一次。列表 B 的长度会有很大差异,并且每次运行都会有所不同。

编辑:我应该提到没有坐标会在列表中出现两次;例如,1,1 不能多次出现在列表 A 中。

【问题讨论】:

  • 你打算用交叉点做什么?
  • 由于范围是固定的,您可以将 (x,y) 表示为单个 24 位数字。将前 12 位用于 x 范围(给您 0-4096),其余用于 y 范围。那么问题就变成了两个列表的交集。

标签: c++ performance algorithm


【解决方案1】:

将 (x,y) 表示为单个 24 位数字,如 cmets 中所述。

按数字顺序维护A(你说它变化不大,所以这应该几乎没有任何成本)。

对于每个 B,在列表上进行二进制搜索。由于 A 大约有 1000 个项目,因此您最多需要 10 次整数比较(在最坏的情况下)来检查成员资格。

如果您有更多内存(大约 2MB)可以使用,您可以创建一个位向量来支持所有可能的 24 位数字,然后对每个项目执行单个位操作以测试成员资格。因此,如果值存在(否则为 0),则 A 将由一个带有位集的 2^24 位数字表示。要测试成员资格,您只需使用适当的位和操作。

【讨论】:

  • 我从来没有想过将坐标表示为一个数字。聪明的!我会对这个建议进行修改,看看效果如何。谢谢!
  • 我花了大约 3 次重读最后一段,然后它终于点击了。我认为这是迄今为止最好的解决方案。我将在下面尝试这个和andand,看看当我把它们砸出来时它们的表现如何。
【解决方案2】:

将列表 A 的坐标放入某种集合(可能是哈希、bst 或堆)中,然后您可以快速查看列表 B 中的坐标是否存在。

取决于您是否希望列表出现在列表中,这将决定您使用的底层数据结构。

哈希擅长告诉您其中是否包含某些内容,尽管取决于它的实现方式,但在尝试查找不在其中的内容时可能表现不佳。

bst 和 heaps 同样擅长告诉您其中是否包含某些内容,但是当其中包含某些内容时,理论上的性能不如哈希。

【讨论】:

    【解决方案3】:

    由于 A 相当静态,您可以考虑构建一个查询结构并检查 B 中的所有元素是否出现在 A 中。一个示例是 std::set > A,您可以像 A.find(element_from_b) 一样查询!= A.end() ...

    所以总运行时间是最坏情况 O(b log a) (其中 b 分别是 B 和 a 中的元素数)。另请注意,由于 a 始终约为 10000,因此 log a 基本上是恒定的。

    【讨论】:

      【解决方案4】:

      根据字典顺序定义排序(先按 x 排序,然后按 y 排序)。根据 O(n log n) 时间内的顺序对两个列表进行排序,其中 n 是每个列表的元素数中的较大者。设置一个指向每个列表的第一个元素的指针,并推进指向较小元素的那个;当指针引用具有相同值的元素时,将它们放入一个集合中(以避免每个列表中的多重性)。最后一部分可以在 O(n) 时间内完成(或 O(m log m),其中 m 是两个列表共有的元素数)。

      更新(基于下面的评论和上面的编辑):由于没有点在每个列表中出现多次,因此您可以使用列表或向量或出队来保存两者共有的点或其他一些(摊销的)常数时间插入实现了 O(n) 时间性能,而与公共元素的数量无关。

      【讨论】:

      • 啊,这实际上是一个非常漂亮的解决方案:P 在没有增加内存开销的情况下获得与 bst 相同的理论性能(我认为),我怀疑它在实践中会更好,因为你没有担心平衡一棵树。
      • 我喜欢这个解决方案 - 感谢您提到可能的重复;我已经编辑了问题以清除它,因为由于问题的性质,不会有任何问题。
      【解决方案5】:

      如果你实现一个 STL 谓词对两对进行排序(即return (R.x < L.x || (R.x==L.x && R.y < L.y)),这很容易。然后你可以调用std::list::sort 对它们进行排序,并调用std::set_intersection 来查找公共元素。无需编写算法

      【讨论】:

        【解决方案6】:

        这种问题只会让我大喊“Bloom Filter”。

        【讨论】:

        • 如果数据很小,使用bloom filter似乎没有意义。它可能会给出错误的答案...
        【解决方案7】:

        如果我理解正确,您想要 X 和 Y 中的公共坐标——(集合)清单 A 和 B 的交集?如果您使用的是 STL:

        #include <vector>
        #include <std>
        using namespace std;
        // ...
        set<int> a; // x coord (assumed populated elsewhere)
        set<int> b; // y coord (assumed populated elsewhere)
        set<int> in; // intersection
        // ...
        set_intersection(a.begin(), a.end(), b.begin(), b.end(), insert_iterator<set<int> >(in,in.begin()));
        

        【讨论】:

          【解决方案8】:

          我认为散列是你最好的选择。

          //伪代码:

          1. 输入:两个列表,每个列表都有 (x,y) 坐标
          2. 找到更长的列表,称之为A
          3. 散列A中的每个元素
          4. 转到另一个列表,将其命名为 B
          5. 散列 B 中的每个元素并在表中查找。
          6. 如果匹配,则在某处返回/存储 (x,y)
          7. 重复 #4 直到结束

          假设A的长度为m,B的长度为n,运行时间为O(m + n) --> O(n)

          【讨论】:

            猜你喜欢
            • 2010-11-24
            • 2012-01-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多