我有一个可变数量的ArrayList,我需要找到它的交集。字符串数量的实际上限可能在35左右,但可能更多。我不想要任何代码,只需要有效的想法。我有一个实现,我即将开始编码,但想听听其他一些想法。
目前,只考虑我的解决方案,看起来我应该有一个渐近的Θ运行时间(n 2 )。
感谢您的帮助!
tshred
编辑:为了澄清,我真的只是想知道有更快的方法来做到这一点。比Θ快(n 2 )。
答案 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)