Algorithm 什么算法可以计算给定集合的幂集?
我希望根据起始数字列表有效地生成数字组合的唯一列表 示例startAlgorithm 什么算法可以计算给定集合的幂集?,algorithm,powerset,superset,Algorithm,Powerset,Superset,我希望根据起始数字列表有效地生成数字组合的唯一列表 示例startlist=[1,2,3,4,5]但是算法应该适用于[1,2,3…n] result = [1],[2],[3],[4],[5] [1,2],[1,3],[1,4],[1,5] [1,2,3],[1,2,4],[1,2,5] [1,3,4],[1,3,5],[1,4,5] [2,3],[2,4],[2,5] [2,3,4],[2,3,5] [3,4],[3,5] [3,4,5] [4,5] 注意。我不想要重复的组合,尽管我可以
list=[1,2,3,4,5]
但是算法应该适用于[1,2,3…n]
result =
[1],[2],[3],[4],[5]
[1,2],[1,3],[1,4],[1,5]
[1,2,3],[1,2,4],[1,2,5]
[1,3,4],[1,3,5],[1,4,5]
[2,3],[2,4],[2,5]
[2,3,4],[2,3,5]
[3,4],[3,5]
[3,4,5]
[4,5]
注意。我不想要重复的组合,尽管我可以接受它们,例如在上面的示例中,我并不真正需要组合[1,3,2],因为它已经以[1,2,3]的形式出现了。您所要求的东西有一个名称。它叫“世界杯” 谷歌搜索“幂集算法”让我想到了这一点 Ruby算法
def动力集!(套)
如果set.empty,是否返回[set]?
p=set.pop
子集=功率集!(套)
子集| subset.map{| x | x |[p]}
结束
幂集直觉
如果S=(a、b、c),则功率集是所有子集的集合
功率集={(),(a),(b),(c),(a,b),(a,c),(b,c),(a,b,c)}
第一个“技巧”是尝试递归地定义
什么是停止状态
S=()具有什么功率集
怎样才能做到这一点
将集合减少一个元素
考虑取出一个元素-在上面的示例中,取出{c}
S=(a,b)然后幂集(S)={(),(a),(b),(a,b)}
少了什么
功率集={(c)、(a,c)、(b,c)、(a,b,c)}
嗯
注意到相似之处了吗?再看看
功率集={(),(a),(b),(c),(a,b),(a,c),(b,c),(a,b,c)}
去掉任何元素
功率集={(),(a),(b),(c),(a,b),(a,c),(b,c),(a,b,c)}is
powerset(S-{c})={(),(a),(b),(a,b)}与联合
{c} U幂集(S-{c})={(c)、(a,c)、(b,c)、(a,b,c)}
powerset(S)=powerset(S-{ei})U({ei}U powerset(S-{ei}))
其中ei是S(单态)的一个元素
伪算法
- 对集合的其余部分递归调用方法
- 返回由以下项的并集组成的集:
- 不带元素的集合的功率集(来自递归调用)
- 同一组(即2.1),但其中的每个元素都与最初取出的元素联合
只需将
0
计数到2^n-1
并根据计数的二进制表示形式打印数字。1
表示您打印该数字,0
表示您不打印该数字。例如:
set is {1, 2, 3, 4, 5}
count from 0 to 31:
count = 00000 => print {}
count = 00001 => print {1} (or 5, the order in which you do it really shouldn't matter)
count = 00010 => print {2}
00011 => print {1, 2}
00100 => print {3}
00101 => print {1, 3}
00110 => print {2, 3}
00111 => print {1, 2, 3}
...
11111 => print {1, 2, 3, 4, 5}
与hobodave的答案相同,但迭代更快(在Ruby中)。它还适用于
数组
和集合
def Powerset(set)
ret = set.class[set.class[]]
set.each do |s|
deepcopy = ret.map { |x| set.class.new(x) }
deepcopy.map { |r| r << s }
ret = ret + deepcopy
end
return ret
end
def动力装置(设置)
ret=set.class[set.class[]
每件事|
deepcopy=ret.map{| x | set.class.new(x)}
deepcopy.map{| r | r来自OP的评论(复制编辑):
这个例子是我实际操作的简化形式。数字是具有属性“Qty”的对象,我想对每个可能的组合的数量求和,然后选择使用数量之和N
在某些其他边界内的大多数对象的组合,例如x
你所面临的是一个优化问题。你所假设的是,解决这个优化问题的正确方法是将它分解为一个枚举问题(这是你所要求的),然后是一个过滤问题(你大概知道怎么做)
你还没有意识到的是,这种解决方案只适用于(a)理论分析,或(b)非常小的n
值。你要求的枚举是n
中的指数,这意味着你最终得到的结果在实践中运行时间太长
因此,找出如何提出您的优化问题,写一个新问题,并编辑此问题以指向它。递归和迭代解决方案,以计算方案中的功率集。但尚未完全测试
(define (power_set set)
(cond
((empty? set) (list '()))
(else
(let ((part_res (power_set (cdr set))))
(append (map (lambda (s) (cons (car set) s)) part_res) part_res)))))
(define (power_set_iter set)
(let loop ((res '(())) (s set))
(if (empty? s)
res
(loop (append (map (lambda (i) (cons (car s) i)) res) res) (cdr s)))))
下面是一个递归解决方案,它类似于已经发布的解决方案。
我没有设法使用“set”Python类型来表示集合集。Python在尝试像“s.add(set())”这样的表达式时说“集合对象是不可损坏的”
另请参见
def generatePowerSet(s,niceSorting=True):
“”“生成给定集的电源集。”。
实现了给定的集合以及集合的返回集合
作为列表。
“niceSorting”选项通过增加子集大小对功率集进行排序。
"""
导入副本
def setCmp(a、b):
“”“比较两个集合(实现为列表)以获得良好的排序”“”
如果len(a)len(b):
返回1
其他:
如果len(a)==0:
返回0
其他:
如果ab:
返回1
其他:
返回0
#将集合“s”的电源集合“ps”初始化为空集合
ps=列表()
如果len=0:
ps.append(list())
其他:
#生成“psx”:sx的功率集,
#它是“s”,没有选择的元素“x”
sx=复制。复制(s)
x=sx.pop()
psx=发电机功率集(sx,False)
#包括“psx”到“ps”
ps.extend(psx)
#将包含“x”的任何集合包括在“ps”中
#通过将“x”添加到“sx”的任何子集,可获得此类包含集
对于psx中的y:
yx=复制。复制(y)
yx.追加(x)
ps.append(yx)
如果需要排序:
ps.sort(cmp=setCmp)
返回ps
断言generatePowerSet([])=[[]]
断言generatePowerSet(['a'])==[[],['a']]
断言generatePowerSet(['a',b'])==[[],['a'],['b'],['a',b']]
断言generatePowerSet(['a','b','c']
def generatePowerSet(s, niceSorting = True):
"""Generate power set of a given set.
The given set, as well as, return set of sets, are implemented
as lists.
"niceSorting" optionnaly sorts the powerset by increasing subset size.
"""
import copy
def setCmp(a,b):
"""Compare two sets (implemented as lists) for nice sorting"""
if len(a) < len(b):
return -1
elif len(a) > len(b):
return 1
else:
if len(a) == 0:
return 0
else:
if a < b:
return -1
elif a > b:
return 1
else:
return 0
# Initialize the power set "ps" of set "s" as an empty set
ps = list()
if len(s) == 0:
ps.append(list())
else:
# Generate "psx": the power set of "sx",
# which is "s" without a chosen element "x"
sx = copy.copy(s)
x = sx.pop()
psx = generatePowerSet(sx, False)
# Include "psx" to "ps"
ps.extend(psx)
# Include to "ps" any set, which contains "x"
# Such included sets are obtained by adding "x" to any subset of "sx"
for y in psx:
yx = copy.copy(y)
yx.append(x)
ps.append(yx)
if niceSorting:
ps.sort(cmp=setCmp)
return ps
assert generatePowerSet([]) == [[]]
assert generatePowerSet(['a']) == [[], ['a']]
assert generatePowerSet(['a', 'b']) == [[], ['a'], ['b'], ['a', 'b']]
assert generatePowerSet(['a', 'b','c']) == [[],
['a'], ['b'], ['c'],
['a', 'b'], ['a', 'c'], ['b', 'c'],
['a', 'b', 'c'] ]
assert generatePowerSet(['a', 'b','c'], False) == [ [],
['a'],
['b'],
['a', 'b'],
['c'],
['a', 'c'],
['b', 'c'],
['a', 'b', 'c'] ]
print generatePowerSet(range(4), True)
def power(a)
(0..a.size).map {|x| a.combination(x).to_a}.flatten(1)
end