python集合交集_如何在python中快速获取集合的所有交集

我想在python中计算有限整数集合(这里实现为列表列表)的所有(不同)交集(为了避免混淆,正式定义在问题的最后):

> A = [[0,1,2,3],[0,1,4],[1,2,4],[2,3,4],[0,3,4]]

> all_intersections(A) # desired output

[[], [0], [1], [2], [3], [4], [0, 1], [0, 3], [0, 4], [1, 2], [1, 4], [2, 3], [2, 4], [3, 4], [0, 1, 4], [0, 3, 4], [1, 2, 4], [2, 3, 4], [0, 1, 2, 3]]

我有一个迭代执行它的算法,但它相当慢(我应该发布吗?),一个测试用例

[[0, 1, 2, 3, 4, 9], [0, 1, 4, 5, 6, 10], [0, 2, 4, 5, 7, 11], [1, 3, 4, 6, 8, 12], [2, 3, 4, 7, 8, 13], [4, 5, 6, 7, 8, 14], [0, 1, 9, 10, 15, 16], [0, 2, 9, 11, 15, 17], [1, 3, 9, 12, 16, 18], [2, 3, 9, 13, 17, 18], [9, 15, 16, 17, 18, 19], [0, 5, 10, 11, 15, 20], [1, 6, 10, 12, 16, 21], [10, 15, 16, 19, 20, 21], [5, 6, 10, 14, 20, 21], [11, 15, 17, 19, 20, 22], [5, 7, 11, 14, 20, 22], [2, 7, 11, 13, 17, 22], [7, 8, 13, 14, 22, 23], [3, 8, 12, 13, 18, 23], [13, 17, 18, 19, 22, 23], [14, 19, 20, 21, 22, 23], [6, 8, 12, 14, 21, 23], [12, 16, 18, 19, 21, 23]]

这需要我大约2.5秒来计算.

Any ideas how to do it fast?

正式定义(实际上没有乳胶模式很难):让A = {A1,…,An}是非负整数的有限集合Ai的有限集合.然后输出应该是集合{A的B:B子集中的集合的交集}.

因此,正式算法将采用A的所有子集的所有交叉点的并集.但这显然是永远的.

非常感谢!

解决方法:

这是一个递归解决方案.在您的测试示例中几乎是即时的:

def allIntersections(frozenSets):

if len(frozenSets) == 0:

return []

else:

head = frozenSets[0]

tail = frozenSets[1:]

tailIntersections = allIntersections(tail)

newIntersections = [head]

newIntersections.extend(tailIntersections)

newIntersections.extend(head & s for s in tailIntersections)

return list(set(newIntersections))

def all_intersections(lists):

sets = allIntersections([frozenset(s) for s in lists])

return [list(s) for s in sets]

在编辑这里是一个更清晰,非递归的相同想法的实现.

如果将空集合的集合定义为通用集合,则问题最容易,并且可以通过获取所有元素的并集来获得足够的通用集合.这是格理论中的标准运动,并且将空集合的集合作为空集合是双重的.如果你不想要它,你总是可以抛弃这个通用集:

def allIntersections(frozenSets):

universalSet = frozenset.union(*frozenSets)

intersections = set([universalSet])

for s in frozenSets:

moreIntersections = set(s & t for t in intersections)

intersections.update(moreIntersections)

return intersections

def all_intersections(lists):

sets = allIntersections([frozenset(s) for s in lists])

return [list(s) for s in sets]

您的测试示例如此之快的原因在于,即使您的集合有24集,因此有2 ** 24(1680万)个潜在交叉点,实际上只有242个(如果不计算则为241个)空的交叉点)不同的交叉点.因此,每次通过循环的交叉点的数量最多为数百.

可以选择24组,以便所有2 ** 24个可能的交叉点实际上是不同的,因此很容易看出最坏情况的行为是指数的.但是,如果在测试示例中,交叉点的数量很少,则此方法将允许您快速计算它们.

潜在的优化可能是在循环之前对集合的大小进行排序.前面处理较小的设置可能导致更早出现的空交叉点,从而使不同交叉点的总数保持较小,直到循环结束.

标签:python,algorithm

来源: https://codeday.me/bug/20190611/1219577.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值