假设集合A有n个元素,集合B有m个元素,两个集合取自某个空间(universe)。
1.1, 首先从最naive的办法开始。对B中元素,挨个测试是不是在A中,交集、并集都是O(m*n),平方级别的算法。
1.2, 将A先排序,O(n*logn),然后,对B中元素,挨个测试是不是在A中,这时可以二分了,O(m*logn),一共是O(n*logn)+O(m*logn)=O((m+n)*logn)。
所以如果m<n的话,对调一下A和B比较好,也就是复杂度是O( (m+n) * log( min(m, n) ) ).
这种思路的本质是,只利用了“A是集合”这个事实,然后对B中元素进行is in A的测试,测试过程需要O(m*logn)的复杂度。
1.3, A、B都排序一下,剩下的工作就和merge-sort很像了,两个指针交替往前走。最坏情况下,需要max(m, n)次比较。
对于基于sorting的办法,也许可以再优化?
2.1,既然已经排完序了,那么立刻就知道两边元素的范围了,譬如 A in [a1, a2], B in [b1, b2],根据这个上下界,可以去掉一部分,然后对真正有overlap的部分,进行merge。极端情况下,根据上下界可以去掉绝大部分乃至全部元素。
另一种思路,用hash-table来。
3.1, A构造一个hash-table,O(n)的插入。然后,对B中元素,挨个测试是不是在表中。这次,连二分也不用了,O(m)的测试,一共是O(m + n)。
代价呢?额外的hash-table,O(n)的table(根据hash-table的性质,通常还会更大)。
其他一些思路,可能适用于某些特定场合。
4.1, 倘若元素范围不大,可以上bitmap(本质上也是hash-table),两个集合用两个bitmap表示,交集就是and,并集就是or,太方便了。
4.2, 另外一个可能的解决方案,bloom filter。另开博文吧,参见:http://www.cnblogs.com/qsort/archive/2011/05/06/2039223.html