有效地找到可变数量的字符串集的交集

时间:2010-05-17 19:03:58

标签: java theory set big-o intersection

我有一个可变数量的ArrayList,我需要找到它的交集。字符串数量的实际上限可能在35左右,但可能更多。我不想要任何代码,只需要有效的想法。我有一个实现,我即将开始编码,但想听听其他一些想法。

目前,只考虑我的解决方案,看起来我应该有一个渐近的Θ运行时间(n 2 )。

感谢您的帮助!

tshred

编辑:为了澄清,我真的只是想知道有更快的方法来做到这一点。比Θ快(n 2 )。

8 个答案:

答案 0 :(得分:42)

Set.retainAll()是你如何找到两组的交集。如果您使用HashSet,那么将ArrayList转换为Set并在所有这些转换中使用retainAll()实际上是O(n)。

答案 1 :(得分:15)

接受的答案很好;作为更新:从Java 8开始,有一种更有效的方法来查找两个Set的交集。

Set<String> intersection = set1.stream()
    .filter(set2::contains)
    .collect(Collectors.toSet());

它效率稍高的原因是因为原始方法必须添加set1的元素,如果它们不在set2中,则必须再次删除它们。这种方法只会在结果集中添加需要的内容。

严格地说,你也可以在Java 8之前做到这一点,但如果没有Stream s,代码就会变得更加费力。

如果两个组的大小差异很大,则您希望在较小的组上进行流式传输。

答案 2 :(得分:14)

Sets.intersection(set1, set2)中还有静态方法Google Guava,它返回两个集合交集的不可修改的视图。

答案 3 :(得分:4)

还有一个想法 - 如果您的数组/集合的大小不同,那么从最小的数组开始是有意义的。

答案 4 :(得分:2)

最好的选择是使用HashSet来存储这些列表的内容而不是ArrayList。如果可以这样做,则可以创建一个临时HashSet,添加要交叉的元素(使用putAll(..)方法)。 tempSet.retainAll(storedSet)和tempSet将包含交集。

答案 5 :(得分:0)

对它们进行排序(n lg n),然后进行二进制搜索(lg n)。

答案 6 :(得分:0)

您可以使用单个HashSet。当set中的对象是alredy时,add()方法返回false。从列表中添加对象并标记错误返回值的计数将在集合+数据中为直方图提供联合(并且计数+ 1等于列表计数的对象是您的交集)。如果将计数抛给TreeSet,则可以提前检测到空交集。

答案 7 :(得分:0)

如果 2 set 有交集需要状态,我使用 Java 8+ 版本代码的下一个片段:

set1.stream().anyMatch(set2::contains)