【问题标题】:Testing for array membership efficiently [duplicate]有效地测试数组成员资格[重复]
【发布时间】:2015-05-10 03:51:18
【问题描述】:

在一次 Java 开发人员采访中,我问了这个问题:

给定两个整数数组,打印出第一个数组中不存在于第二个数组中的值。总时间复杂度应该是O(n)。

我想出的方法是:

  1. 使用哈希表存储第二个数组的值。
  2. 现在检查哈希表中是否存在第一个数组的值。如果没有,请打印这些值。

还有其他更有效的方法来实现吗?

【问题讨论】:

  • 数组是否排序?如果没有对数组进行排序,我不确定这在 O(n) 中是否可行。排序的最小理论复杂度为 n log n,已经不符合要求。
  • @DanSimmons 没有未排序的数组

标签: java arrays sorting data-structures


【解决方案1】:

我们将假设两个数组的长度大致相同,因此使用 n 来描述它们的长度。 (否则我们需要引入一个新变量。)

替代品概述:

线性搜索:如果我们将第二个数组存储为未排序的数组/列表,那么每次搜索需要 O(n) 时间并且总时间为O(n2)。

二分查找:如果我们对第二个数组进行排序,则需要 O(n log n) 时间。每个查询需要 O(log n) 时间,总共需要 O(n log n ) 时间。

平衡树:如果我们将第二个数组存储在 TreeSet 中,则每次搜索需要 O(log n) 时间总共 O(n log n) 时间。

哈希表:如果我们像您提到的那样将第二个数组存储在 HashSet 中,则每次插入需要 O(1) 摊销时间,每次搜索需要 O(1) 次,总共需要 O(n) 次。

位向量:如果我们创建一个 232 元素位向量来覆盖所有可能的 Java int 或 Integer 值,我们可以添加每个元素的第二个数组并测试是否存在 O(1) 时间内的值,总共需要 O(n) 时间.然而,对于 232 个元素的初始化,有一个非常昂贵的常数项。

下限参数:第二个数组的长度为 O(n)。如果我们没有扫描整个数组,就不可能准确地判断一个值是否在第二个数组中。因此,解决这个问题的绝对最小时间是 Ω(n)。这意味着 O(n) 是我们能做到的最好的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-12
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 2012-03-02
    • 2012-03-15
    • 1970-01-01
    • 2018-08-11
    相关资源
    最近更新 更多