【问题标题】:Inconsistencies in Big-O of removing from an ArrayList vs a Hash Table?从 ArrayList 与 Hash Table 中删除的 Big-O 不一致?
【发布时间】:2013-12-29 03:32:25
【问题描述】:

我正在查看this website,它列出了各种操作的大 O 复杂性。对于动态数组,删除复杂度是 O(n),而对于 Hash Tables,它是 O(1)。

对于像 ArrayLists 这样的动态数组 O(n),这必须意味着从中心移除一些值然后将每个索引移到一个以保持数据块连续的操作。因为如果我们只是删除存储在索引 k 处的值而不是移动,那就是 O(1)。

但是在线性探测的哈希表中,删除是一样的,你只需通过哈希函数运行你的值,进入保存数据的动态数组,然后删除存储在其中的值。

那么为什么哈希表获得 O(1) 信用,而动态数组获得 O(n)?

【问题讨论】:

  • 为什么它们应该是“一致的”?您是否考虑过您的假设不正确的可能性?
  • 我建议你删除 java 标签,并提到 ArrayList,如果你真的想用 language-agnostic 替换它,但 data-structures 也可以,除非这个问题是专门关于Java API 的哈希表实现(请注意,它不使用线性探测,它使用单独的链接,如 Stephen pointed out)。

标签: java data-structures computer-science time-complexity


【解决方案1】:

这已解释here。关键是每个动态数组的值的数量保持在一个恒定值。

编辑:正如 Dukeling 所指出的,我的回答解释了为什么具有 单独链接 的哈希表具有 O(1) 的删除复杂性。我应该补充一点,在您正在查看的网站上,哈希表被认为具有 O(1) 删除复杂性,因为它们通过单独的链接而不是线性探测来分析哈希表。

【讨论】:

  • 问题是关于线性探测,而不是单独的链接。好吧,我假设您在谈论单独的链接,否则您所说的实际上没有意义。
【解决方案2】:

哈希表的关键在于它们接近最佳情况,其中最佳情况意味着每个存储桶有一个条目。显然,您可以毫不费力地接受从存储桶中删除唯一条目需要 O(1) 时间。

【讨论】:

  • 很难判断您是在谈论线性探测还是分离链接(它似乎是分离链接,但另一方面,如果它也是线性探测)。该问题询问线性探测。我想我会指出这一点。
  • 我说的是两者。由于线性探测与HashMap 无关,我认为OP 并不关心详细的区别。
【解决方案3】:

当哈希冲突很多时,使用线性探测时肯定需要做很多移位。

但哈希表的复杂性是在Simply Uniform Hashing 的假设下,这意味着它假设会有最少数量的哈希冲突。

发生这种情况时,我们只需要删除一些值,然后不移动任何值或移动少量(基本上是恒定的)值。

【讨论】:

    【解决方案4】:

    当您谈论算法的复杂性时,您实际上需要讨论具体的实现。

    • 没有称为“哈希表”(显然!)或“哈希表”的 Java 类。

    • 有名为HashMapHashtable 的Java 类,它们确实删除了O(1)

    但它们的工作方式并不像您认为的(全部?)哈希表那样工作。具体来说,HashMapHashtable 被组织为指向“链”的指针数组。

    这意味着删除包括找到适当的链,然后遍历链以找到要删除的条目。第一步是常数时间(包括计算哈希码的时间。第二步与哈希链的长度成正比。但假设哈希函数好,哈希链的平均长度是一个很小的常数。因此,删除的总时间平均为 O(1)。


    哈希链平均较短的原因是HashMapHashtable类在“加载因子”(数组大小与条目)超过预定值。假设散列函数非常均匀地分布(实际)密钥,您会发现链的长度大致相同。假设数组大小与条目总数成正比,则实际加载因子将是平均哈希链长度。

    如果散列函数没有均匀地分配键,这个推理就失效了。这会导致您遇到大量散列冲突。实际上,最坏的情况是所有键都具有相同的散列值,并且它们最终都位于具有所有 N 个条目的单个散列链上。在这种情况下,删除涉及到搜索具有 N 个条目的链......这使得它成为O(N)


    事实证明,同样的推理可以应用于其他形式的哈希表,包括条目存储在哈希数组本身中的那些,并且通过重新哈希扫描来处理冲突。 (再一次,“技巧”是在负载因子过高时扩展哈希表。)

    【讨论】:

    • Java 类也不能包含空格,所以我的想法是 OP 实际上并不是在谈论 Java 类,而只是一般的哈希表,带有线性探测(明确提到),而不是而不仅仅是输入错误,并且不知道 Java 类不使用线性探测。
    猜你喜欢
    • 2014-01-06
    • 2012-02-07
    • 2020-02-13
    • 2012-12-15
    • 2019-06-02
    • 1970-01-01
    • 1970-01-01
    • 2018-08-07
    • 1970-01-01
    相关资源
    最近更新 更多