更新:不迭代任何集合,只使用集合操作。
这个算法是通过构建结果集来完成的,也就是说,我们每次看到一个新的源集合时,都会修改现有的唯一元素集合和/或添加新的集合。
这个想法是,每个新的集合都可以分成两部分,一部分是已经见过的值,另一部分是新的唯一值。对于第一部分,它进一步被当前结果集拆分成各种子集(最多是已见过的源集合的幂集数)。对于每个这样的子集,它也分为两部分,一部分与新的源集合相交,另一部分则没有。任务是更新每个类别的结果集。
关于集合操作的复杂度,应该是O(n*2^n)。对于OP发布的解决方案,我认为复杂度应该是O(2^(2n)),因为len(resulting_sets)
在最坏情况下有2^n个元素。
最初的回答:
该算法通过构建结果集来实现,即每次查看新的源集合时,都会修改现有的唯一元素集合和/或添加新的集合。每个新的集合可以分成两部分,一部分是已经见过的值,另一部分是新的唯一值。对于第一部分,它被当前结果集拆分成各种子集(最多是已见过的源集合的幂集数)。对于每个这样的子集,它也分为两部分,一部分与新的源集合相交,另一部分则没有。任务是更新每个类别的结果集。关于集合操作的复杂度,应该是O(n*2^n)。对于OP发布的解决方案,我认为复杂度应该是O(2^(2n)),因为len(resulting_sets)
在最坏情况下有2^n个元素。
def solution(sets):
result_sets = []
for sid, s in enumerate(sets):
new_sets = []
for unique_elements, membership in result_sets:
intersect = unique_elements & s
if len(intersect) == len(unique_elements):
membership.append(sid)
elif len(intersect) != 0:
unique_elements -= intersect
new_sets.append((intersect, membership + [sid]))
s -= intersect
if len(s) == 0:
break
else:
new_sets.append((s, [sid]))
result_sets.extend(new_sets)
print(result_sets)
sets = [{1, 2, 3}, {1, 4, 7}, {1, 4, 5}]
solution(sets)
--------------- 最初的回答如下 ---------------
这个想法是找到每个唯一元素的"成员资格",即它属于哪些集合。然后,我们创建一个字典来根据它们的成员资格将所有元素分组,生成所需的集合。复杂度为O(n*len(sets)),在最坏情况下为O(n^2)。
def solution(sets):
union = set().union(*sets)
numSets = len(sets)
numElements = len(union)
memberships = {}
for e in union:
membership = tuple(i for i, s in enumerate(sets) if e in s)
if membership not in memberships:
memberships[membership] = []
memberships[membership].append(e)
print(memberships)
sets = [{1, 2, 3}, {1, 4, 7}, {1, 4, 5}]
solution(sets)