问题:
给定两个Collection<?>
,检查两者是否包含相同的元素。
解决方案1:
boolean equals = c1.containsAll(c2) && c2.containsAll(c1);
解决方案2:
boolean equals = new HashSet<?>(c1).equals(new HashSet<?>(c2));
我认为解决方案2 比解决方案1 ( O(n)更高效( O(n)) 2))。
我是对还是错过了什么?
答案 0 :(得分:8)
这些的大O复杂性是正确的,解决方案1涉及迭代另一个列表中每个项目的一个列表(O (n)
),即O (n^2)
。解决方案2涉及两个O (n)
个副本,并在一个集合(O (n)
)上进行迭代,并对另一个集合进行O (1)
.contains()
检查。总而言之,那只是O (n)
。
但是根据你的约束,你可以做得更好(不是渐近更好,只是更好的实现)。
由于我们假设没有重复元素,因此无需进行第二次.containsAll()
检查。只需检查它们的大小是否相同(可能是O (n)
,但仍然比复制O (n^2)
检查更好)然后执行.containsAll()
。
无需将c2
转换为Set
,因为它会反复进行迭代;只需转换c1
并使用.containsAll()
。
您可以使用instanceof Set
来测试c1
或c2
是否已经是Set
,并使用该对象的.containsAll()
方法;这将在O (n)
时间运行,即使其他对象不是一个集合,也可以避免解决方案2具有的复制开销。
答案 1 :(得分:2)
如dimo414所述,一般来说,是的。但你总是可以做得更好(不是渐近更好,只是更快)。它变得更加复杂:
if (c1.size() != c2.size()) {
return false;
} else if (c1 instanceof Set) {
return c1.containsAll(c2);
} else if (c2 instanceof Set) {
return c2.containsAll(c1);
} else {
return new HashSet<>(c1).containsAll(c2);
}
还有一些慢size
的集合,您可能需要特别处理......