有没有一种算法,可以在线性时间内计算两个集合的交集?
我可以运行两个for
循环来检查所有元素对,并记录我在两个集合中发现的元素。然而,运行时间将是O(n2)。如何在O(n)时间内完成此操作?
有没有一种算法,可以在线性时间内计算两个集合的交集?
我可以运行两个for
循环来检查所有元素对,并记录我在两个集合中发现的元素。然而,运行时间将是O(n2)。如何在O(n)时间内完成此操作?
这取决于你的集合实现方式。
如果你使用哈希集合(O(1) 查找),那么其他海报所指出的方法是正确的。遍历第一个集合中的所有元素,如果它也在第二个集合中,就把它加入到结果中。这样做的时间复杂度是 O(n)。
如果你使用树集合(O(lg n) 查找),那么这个方法也可以工作,但它的时间复杂度是 O(n lg n)。你可以通过使用一种 O(n) 的算法来提高效率。我假设你有一种迭代器,能够按照升序遍历两个集合中的元素。如果有这样的迭代器,问题就变成了“给定两个已排序列表,找到它们的交集”。可以使用修改过的合并两个范围的算法来解决。方法是跟踪两个迭代器,在每一步中比较范围的前两个元素。如果它们相等,则将该元素添加到交集中,并将两个迭代器都向前移动。如果第一个元素小于第二个元素,则将第一个迭代器向前移动。如果第一个元素大于第二个元素,则将第二个迭代器向前移动。由于每次迭代至少消耗一个元素,而总共只有 O(n) 个元素,所以该算法的时间复杂度是 O(n)。
我想知道为什么没有人提到哈希表。
O(n)
intersection(a, b):
result = new empty set
for x in b:
if a contains x:
add x to result
return result
contains
测试是固定时间(例如在使用哈希表作为实现的集合中),那么这个算法的时间复杂度为O(n)
。O(n^3)
的时间,而是需要O(3n) = O(n)
步骤,假设contains
和insert
是常数(=O(1)
)。 - fkarg合并这两个数组,并计算每个元素在这个组合数组中的出现次数,并将它们放入一个新的数组中。然后检查这个计数数组是否包含2的条目,这些元素是两个集合的交集。
对于集合1中的所有元素:检查该元素是否在集合2中。您可以实现具有平摊O(1)查找时间的集合。
FUNCTION: INTERSECTION ( LIST A, LIST B )
{
CREATE C AS EMPTY LIST
FOR EVERY: NUMBER n IN A
{
IF BINARY-SEARCH(n) IN B
{
ADD n TO C
}
}
RETURN C
}
时间复杂度 = O(n O(二分查找)) = O(n log n)
如果列表B被哈希
,那么我们有BIG-THETA(C n + T(hash))
其中BIG-THETA是渐近平均值,C
是一个常数
,T(hash)
是哈希函数所需的时间。