给定大量集合,大小相同(称之为 S = {s 1 ,...,s n } ),我想找到重叠至少 M的所有对( s i ,s j )
因此,如果 M = 2 且 S 由
组成我想识别对(s 1 ,s 2 ),(s 2 ,s 4 ),和(s 3 ,s 4 )。
直接的方法比较每一对并检查交叉点的大小,但考虑到我使用的集合的数量和集合的大小,这非常慢(类似于 O(log(m)n 2 )其中 m 是集合的大小?)。
我已经四处寻找并且没有找到类似的问题(尽管this answer is probably relevant)。任何帮助将不胜感激!
答案 0 :(得分:2)
按值增加
伪代码:
typedef V => type of values;
list<Set> S;
Map<V, list<int>> val2sets;
for(int setIdx=0; setIdx < S.length; ++setIdx){
foreach(V v in S[setIdx]) {
val2sets[v].push(setIdx);
}
}
int[][] setIntersectCount;
foreach(V as v ,list<int> as l in val2sets) {
for(int i=0; i < l.length; ++i){
for(int j=i+1; j < l.length; ++j){
setIntersectCount[i][j]++;
if(setIntersectCount[i][j] == 2){
printf("set {0} and {1} are a pair\n", i, j);
}
}
}
}
至于复杂性:
让S =集合# 让M =集合中的成员数量。 设V =集合中唯一值的数量。
O(SM)
生成val2sets
至于读取所有值并匹配每个2 ...,
它的最大值为O(V x S ^ 2),但概率更接近O(SM)
,因为均匀性将表明并非所有集合都具有所有共同的元素。
P.S。希望我的计算没有任何错误。
值得注意的是:我没有计算Naieve方法的复杂性:)