给定两个列表(不一定排序),找到这些列表的交集的最有效的非递归算法是什么?
给定两个列表(不一定排序),找到这些列表的交集的最有效的非递归算法是什么?
Answers:
您可以将第一个列表的所有元素放入哈希集中。然后,迭代第二个,并针对其每个元素,检查哈希以查看其是否存在于第一个列表中。如果是这样,请将其输出为相交的元素。
您可能想看看Bloom过滤器。它们是位向量,可为元素是否为集合的成员提供概率性答案。集合交集可以通过简单的按位与运算来实现。如果您有大量的空交集,则布隆过滤器可以帮助您快速消除这些交集。但是,您仍然必须借助此处提到的其他算法之一来计算实际的交点。 http://en.wikipedia.org/wiki/Bloom_filter
不带哈希,我想您有两个选择:
O(n + m)
并非总是可能的。
O(n lg n) * 2 + O(n) * 2
与相同O(n lg n)
。
从eviews功能列表中,它似乎支持复杂的合并和连接(如果按照数据库术语中的“ join”,它将计算交集)。现在浏览您的文档:-)
此外,eviews拥有自己的用户论坛-为什么不在那里询问_
使用set 1构建一个二叉搜索树,O(log n)
并使用set2进行迭代并搜索BST m X O(log n)
总数O(log n) + O(m)+O(log n) ==> O(log n)(m+1)
这是我想出的另一种可能的解决方案,它在时间复杂度上采用O(nlogn),而没有任何额外的存储。您可以在这里查看https://gist.github.com/4455373
它是这样工作的:假设这些集合不包含任何重复,请将所有集合合并为一个并对它进行排序。然后循环遍历合并的集合,并在每次迭代中在当前索引i和i + n之间创建一个子集,其中n是Universe中可用集合的数量。我们在循环时寻找的是一个大小为n的重复序列,该序列等于宇宙中集合的数量。
如果i处的那个子集等于n处的那个子集,这意味着i处的元素重复了n次,这等于集合的总数。并且由于任何集合中都没有重复,这意味着每个集合都包含该值,因此我们将其添加到交集。然后我们将索引移动i + i和n之间剩余的值,因为这些索引中肯定没有一个会形成重复序列。
首先,使用quicksort对两个列表进行排序:O(n * log(n)。然后,通过首先浏览最低值并添加公共值来比较列表,例如,在lua中):
function findIntersection(l1, l2)
i, j = 1,1
intersect = {}
while i < #l1 and j < #l2 do
if l1[i] == l2[i] then
i, j = i + 1, j + 1
table.insert(intersect, l1[i])
else if l1[i] > l2[j] then
l1, l2 = l2, l1
i, j = j, i
else
i = i + 1
end
end
return intersect
end
这是列表的O(max(n, m))
位置n
和m
大小。
在PHP中,类似
function intersect($X) { // X is an array of arrays; returns intersection of all the arrays
$counts = Array(); $result = Array();
foreach ($X AS $x) {
foreach ($x AS $y) { $counts[$y]++; }
}
foreach ($counts AS $x => $count) {
if ($count == count($X)) { $result[] = $x; }
}
return $result;
}