【问题标题】:Can we use maps for searching instead of binary search?我们可以使用地图搜索而不是二分搜索吗?
【发布时间】:2020-09-23 20:11:30
【问题描述】:

地图提供 O(1) 查找。难道我们不能遍历数组一次并建立一个与其索引对应的映射(与数组相反),当我们想搜索一些东西时,我们可以调用map[VALUE],它会返回索引。

它可能不适用于数组中的大值,但假设a[i]<10^5,我们不能这样做而不是二进制搜索吗?然后,每个查询将是 O(1)。

P.S:我的意思是无序地图..

【问题讨论】:

  • 是的,为什么你认为你不能?
  • “地图提供 O(1) 查找”编号 std::mapO(log(n))std::unordered_map 平均为 O(1)
  • 当然可以……但这里有个问题……如果数组中的值发生变化怎么办?您还必须更新地图。如果数组中有多个相同的值怎么办?你会怎么处理呢?
  • 不要忘记,虽然O(1) 可能意味着“恒定时间”,但“时间”可能是巨大的。 O(n) 算法可以轻松胜过 O(1) 算法,如果后者每次查找有 1 年的恒定开销,而前者每次查找使用 (1ms * n)。算法复杂度与现实生活中的运行时间不同。
  • 在数据库术语中,您描述的是一个索引表。您的所有数据都放在std::vector 中。索引表是std::map<key, vector-index>。您可以创建多个索引表,通常每个索引字段一个,而不必对std::vector 中的数据进行排序。

标签: python c++ algorithm data-structures


【解决方案1】:

以下是您可能需要考虑的问题 -

  • 不能在map中存储多个相同值的元素

  • 查找时间是O(log(n))而不是O(1)

  • 地图中发生的事情并不是魔法,它可以让我们在更短的时间内访问它。在unordered_map 的后台有一个散列过程正在进行,它给出了O(1),这也需要时间。所以,大 O 隐藏了一个很大的常数时间因子。标准map 为您提供O(logn) 查找,其时间复杂度与数组中的二进制搜索相同。


您获得的搜索平均时间复杂度相同大致相同。在 C++ 中使用标准映射将遇到的主要问题是它无法容纳具有相同值的多个元素。使用 map 可能获得的优势之一是删除和插入时间将是 O(logn)

因此,如果您知道您将处理的数据集没有重复元素和/或会有频繁添加/删除元素,那么在这种情况下,您当然可以将 map 视为更好的选择

【讨论】:

  • 为什么地图要散列?一个unordered_map,当然是O(1)
  • 通常,散列的开销与比较键的开销相当,因此常数因子不太可能大到足以主导搜索。
  • 与数组中的二进制搜索相比,映射的主要优点是您可以进行 O(log n) 的插入和删除以及查找。
  • @Barmar 是的。但这也取决于数据的大小。有时散列可能比您提到的比较密钥要昂贵得多(考虑到冲突和所有)。我可能错了,但这就是我到目前为止的想法
  • 除非数据集很大,否则这些都没有太大区别。
【解决方案2】:

由于确切的运行时间将取决于密钥的长度和类型、它们的分布、数量,因此建议针对您的特定应用程序进行基准测试。

【讨论】:

    【解决方案3】:

    hash table,就像 Python 字典一样,将提供每次查找的摊销固定平均成本。

    对于大型数据集,这可能会成为二进制搜索的有趣替代方案。

    出于以下原因,某些算法可能绝对需要二进制搜索:

    当查找值不在数据集中时,二分查找仍然可以分辨出数据集中大于查找值的最小值和小于查找值的最大值,同时 O(logn) 成本。

    对我来说,重复问题不是问题,因为您可以在数组中存储 (value, frequency) 或 (value, [payload1, payload2, ...]) 的元组,因此仍然使用哈希表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-13
      • 1970-01-01
      • 2020-09-01
      • 2016-06-24
      • 1970-01-01
      • 2014-04-28
      相关资源
      最近更新 更多