假设我有一个包含6个球(3个白色和3个黑色)的球包。 我想查找给定长度的所有可能子集,忽略顺序。在上面的情况中,我只能从包中抽取3个球组合:
我已经用我选择的语言找到了一个完全符合这个标准的库,但我觉得它对于更多的数字来说很慢。例如,一个包含15个白色,1个黑色,1个蓝色,1个红色,1个黄色和1个绿色的包,只有32个10个球的组合,但产生结果需要30秒。
是否有一种有效的算法可以找到我自己可以实现的所有组合?也许这个问题并不像我最初想的那样微不足道......
注意:我甚至不确定用正确的技术词来表达这一点,所以请随时更正我的帖子的标题。
答案 0 :(得分:5)
您可以比一般选择算法做得更好。关键的见解是同时处理每种颜色的球,而不是逐个处理每个球。
我在python中创建了一个未优化的算法实现,可以在几毫秒内正确找到测试用例的32个结果:
def multiset_choose(items_multiset, choose_items):
if choose_items == 0:
return 1 # always one way to choose zero items
elif choose_items < 0:
return 0 # always no ways to choose less than zero items
elif not items_multiset:
return 0 # always no ways to choose some items from a set of no items
elif choose_items > sum(item[1] for item in items_multiset):
return 0 # always no ways to choose more items than are in the multiset
current_item_name, current_item_number = items_multiset[0]
max_current_items = min([choose_items, current_item_number])
return sum(
multiset_choose(items_multiset[1:], choose_items - c)
for c in range(0, max_current_items + 1)
)
测试:
print multiset_choose([("white", 3), ("black", 3)], 3)
# output: 4
print multiset_choose([("white", 15), ("black", 1), ("blue", 1), ("red", 1), ("yellow", 1), ("green", 1)], 10)
# output: 32
答案 1 :(得分:1)
不,您不需要搜索所有可能的替代方案。一个简单的递归算法(如@recursive给出的算法)会给你答案。如果你正在寻找一个实际输出所有组合的函数,而不仅仅是有多少,这里是用R编写的版本。我不知道你在用什么语言,但翻译它应该非常简单任何事情,虽然代码可能会更长,因为R擅长这种事情。
allCombos<-function(len, ## number of items to sample
x, ## array of quantities of balls, by color
names=1:length(x) ## names of the colors (defaults to "1","2",...)
){
if(length(x)==0)
return(c())
r<-c()
for(i in max(0,len-sum(x[-1])):min(x[1],len))
r<-rbind(r,cbind(i,allCombos(len-i,x[-1])))
colnames(r)<-names
r
}
这是输出:
> allCombos(3,c(3,3),c("white","black"))
white black
[1,] 0 3
[2,] 1 2
[3,] 2 1
[4,] 3 0
> allCombos(10,c(15,1,1,1,1,1),c("white","black","blue","red","yellow","green"))
white black blue red yellow green
[1,] 5 1 1 1 1 1
[2,] 6 0 1 1 1 1
[3,] 6 1 0 1 1 1
[4,] 6 1 1 0 1 1
[5,] 6 1 1 1 0 1
[6,] 6 1 1 1 1 0
[7,] 7 0 0 1 1 1
[8,] 7 0 1 0 1 1
[9,] 7 0 1 1 0 1
[10,] 7 0 1 1 1 0
[11,] 7 1 0 0 1 1
[12,] 7 1 0 1 0 1
[13,] 7 1 0 1 1 0
[14,] 7 1 1 0 0 1
[15,] 7 1 1 0 1 0
[16,] 7 1 1 1 0 0
[17,] 8 0 0 0 1 1
[18,] 8 0 0 1 0 1
[19,] 8 0 0 1 1 0
[20,] 8 0 1 0 0 1
[21,] 8 0 1 0 1 0
[22,] 8 0 1 1 0 0
[23,] 8 1 0 0 0 1
[24,] 8 1 0 0 1 0
[25,] 8 1 0 1 0 0
[26,] 8 1 1 0 0 0
[27,] 9 0 0 0 0 1
[28,] 9 0 0 0 1 0
[29,] 9 0 0 1 0 0
[30,] 9 0 1 0 0 0
[31,] 9 1 0 0 0 0
[32,] 10 0 0 0 0 0
>