删除作为子集的集合

时间:2017-03-04 17:30:36

标签: algorithm

假设您有两个整数集列表。将它们称为A和B. A中的每个集合都可以包含在B中的一个集合中。找到A中所有元素的最有效算法是什么,以便一组中没有包含B?

1 个答案:

答案 0 :(得分:1)

为了尝试修剪搜索空间,我们可以尝试一些检查和过滤器作为搜索的一部分。在评论中举例说明,

A = [{1,2},{1,4},{3,4,7}]
B = [{2,3,4},{1,2,4},{1,2,5,6}] 

从集合中唯一元素的O(n)枚举开始,作为指向它们所属集合的跨相关索引的键:

1: A: {0,1}, B: {1,2}
2: A: {0}  , B: {0,1,2}
3: A: {2}  , B: {0}
4: A: {1,2}, B: {0,1}
5: A: {}   , B: {2}
6: A: {}   , B: {2}
7: A: {2}  , B: {}

我们可以立即在A中留出包含B中未找到的元素的集合,例如A的第三集。

现在,我们将遍历A中尚未排除的每个集合,并检查B中是否存在至少一个集合的相应完整交集。由于您的案例中的集合索引数量为数百万,而不是最初完全遍历B我们将把我们对B的检查分成几个部分,每个k集合,比如1024.此外,为了表示这1024个集合索引,我们将它们分成16个64位集合每个位,所以我们可以按位 - 和(和)一个与另一个。

在此遍历期间的任何时候,如果AND操作导致零,我们将从提前退出中受益:

set A[0] => elements 1,2 => set-index-intersection in B: b110 & b111 => match
set A[1] => elements 1,4 => set-index-intersection in B: b110 & b11  => match

总的来说,逐节工作,我们正在查看大约10 * 16个操作,以检查A中的一个集合是否包含在k B集的当前部分中的一个集合中。换句话说,我们已将操作次数从10,000,000减少到160,000,以便对A中的一组进行全面检查(B中每百万套)。这是62的因素。