是否存在一个算法,给定两组,在线性时间内计算它们的交点?
我可以运行两个for
循环来检查所有元素对,记录我在两个集合中找到的元素。但是,运行时间为O(n 2 )。我如何在O(n)时间内完成这项工作?
答案 0 :(得分:34)
这取决于你的设定实施。
如果你有一个哈希集(O(1)查找),那么所有其他海报指示的方法是正确的。迭代第一组中的所有元素。如果它在第二组中,则将其添加到结果中。这在O(n)时间内运行。
如果你有一个树集(O(lg n)查找),那么这种方法将起作用,但它在O(n lg n)时间内运行。你可以做得更好;有一个O(n)解决方案。我假设你有某种迭代器可以按升序遍历两个集合的元素。如果你这样做,那么问题是“按排序顺序给出两个列表,找到它们的交集。”这可以使用您用于合并两个范围的算法的修改版本来完成。我们的想法是跟踪两个迭代器。在每个步骤中,比较范围的第一个元素。如果它们相等,则将元素添加到交集处并向前推进两个迭代器。如果第一个小于第二个,则推进第一个迭代器。如果第一个元素更大,则前进第二个迭代器。这在时间O(n)中运行,因为每次迭代消耗至少一个元素,并且总共只有O(n)个元素。
答案 1 :(得分:9)
我想知道没人提到哈希表 无论你的set实现如何(即使'set'在这里意味着一个简单的数组),你可以
O(n)
答案 2 :(得分:2)
intersection(a, b):
result = new empty set
for x in b:
if a contains x:
add x to result
return result
如果contains
测试是常量时间(例如在使用哈希表作为实现的集合中),则此算法为O(n)
。
答案 3 :(得分:2)
组合两个数组并计算此组合数组中每个元素的出现次数,并将它们放在一个新数组中。然后检查此计数数组以查找包含2的条目,这些元素在两个集合的交集中。
答案 4 :(得分:0)
对于集合1中的所有元素:检查该元素是否在集合2中。您可以实现具有分摊O(1)查找时间的集合。
答案 5 :(得分:0)
如果订购了两个列表中的一个,那么我们可以从无序列表
开始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
}
Time Complexity = O(n O(BINARY-SEARCH)) = O(n log n)
如果列表B是hashed
,那么我们BIG-THETA(C n + T(hash))
其中BIG-THETA是渐近平均值,C
是constant
并且T(hash)
是散列函数所需的时间