我被问到这个面试问题。获得两个集合之间交集的最佳和有效方式,一个非常大,另一个很小。 Java Collection基本上是
答案 0 :(得分:0)
没有其他信息,您可以做的是在执行n x m
比较时节省时间,如下所示:
big
和small
成为尺寸n
和m
的集合。intersection
成为交叉集合(暂时为空)。hashes
成为small
中所有元素的哈希集合。object
中的每个big
,让h
为其哈希整数。hash
集合中的每个hashes
值,如果hash = h
,则将object
与散列为{{1}的small
元素进行比较}。如果相同,请将hash
添加到object
。因此,我们的想法是比较哈希而不是对象,只比较对象的哈希值是否重合。
请注意,intersection
哈希的附加集合是可以接受的,因为这个可能很小的集合的大小。另请注意,该算法计算small
哈希值和相对较少的对象比较。
以下是Smalltalk中的代码
n + m
Smalltalk代码非常紧凑,因为发送到set := small asSet.
^big select: [:o | set includes: o]
的消息includes:
的工作方式如上面的步骤5所述。它首先比较哈希,然后根据需要比较对象。 set
也是在步骤5中表达选择的一种非常紧凑的方式。
<强>更新强>
如果我们枚举两个集合的元素之间的所有比较,我们将不得不考虑select:
对对象,这将考虑订单n x m
(big-O表示法)的复杂性。另一方面,如果我们将小集合放入散列集合(就像我在Smalltalk示例中所做的那样),每次我们必须检查O(nm)
是否包含small
对象时发生的内部测试将具有big
的复杂性。鉴于O(1)
集合的散列为small
,此方法的总复杂度为O(m)
。
答案 1 :(得分:0)
我们分别调用两个集合large
和small
。
Java Collection
是一个Abstract
类 - 您实际上无法直接使用它 - 您必须使用Collection
的具体子类之一。对于此问题,您可以使用Set
s。 Set
只包含唯一元素,并且方法为contains(Object o)
。默认情况下,它的子类SortedSet
按升序创建。
将small
复制到Set
。它现在没有重复的值。将large
复制到第二个Set
,这样我们就可以使用其contains()
方法。创建一个名为intersection
的第三个集合,用于保存交叉点结果。
for-each
中的 small
元素检查large.contains(element_from_small)
每次找到匹配项时,intersection.add(element_from_small)
在运行small
结束时,您将拥有两个原始集合中所有对象的交集,没有重复项。如果您想订购,请将其复制到SortedSet
,然后按升序排列。