Algorithm 随机访问固定字母表中3个符号的已排序集合的枚举
假设我们有一个字母表,比如说5个字符:ABCDE 我们现在要列举其中3个字母的所有可能集合。每个字母在一个集合中只能出现一次,字母的顺序无关紧要(因此集合中的字母应该被排序) 因此,我们得到以下集合:Algorithm 随机访问固定字母表中3个符号的已排序集合的枚举,algorithm,sorting,combinatorics,Algorithm,Sorting,Combinatorics,假设我们有一个字母表,比如说5个字符:ABCDE 我们现在要列举其中3个字母的所有可能集合。每个字母在一个集合中只能出现一次,字母的顺序无关紧要(因此集合中的字母应该被排序) 因此,我们得到以下集合: ABC 阿布德 阿贝 ACD 王牌 艾德 卡介苗 BCE 溴化二苯醚 CDE 总共10套。顺序是按词典编纂的 现在,我们假设字母表长度为N(本例中为5),集合长度为M(本例中为3)。知道N和M,如果可能的话,我们怎么可能: 告诉最坏情况下组合的总数O(M+N)(本例中的答案是10) 在最坏情况下输
N
(本例中为5),集合长度为M
(本例中为3)。知道N
和M
,如果可能的话,我们怎么可能:
O(M+N)
(本例中的答案是10)O(M+N)
用
O(M^N)
复杂度生成整个列表是很简单的,但我想知道是否有更好的解决方案。第一个问题的答案很简单:它是C(N,r)
,我们要从一组大小N
中选择r
项的所有组合。公式包括:
C(n,r) = n! / (r! (n-r)!)
选择第i个组合而不计算所有其他组合的能力取决于是否具有将组合编号i与组合关联的编码。这将是更具挑战性的,需要更多的思考
(编辑)
仔细考虑这个问题后,Python中的解决方案如下所示:
from math import factorial
def combination(n,r):
return factorial(n) / (factorial(r) * factorial(n-r))
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def showComb(n,r,i,a):
if r < 1:
return ""
rr = r-1
nn = max(n-1,rr)
lasti = i
i -= combination(nn,rr)
j = 0
while i > 0:
j += 1
nn = max(nn-1,1)
rr = min(rr,nn) # corrected this line in second edit
lasti = i
i -= combination(nn,rr)
return a[j] + showComb(n-j-1,r-1,lasti,a[(j+1):])
for i in range(10):
print(showComb(5,3,i+1,alphabet))
。。。这证实了这120个例子都是正确的
我还没有精确计算时间复杂度,但是对
showComb()
的调用次数将是r
,而while
循环将执行n
次或更少。因此,在这个问题的术语中,如果我们假设factorial()
函数可以在恒定时间内计算,我非常确定复杂性将小于O(M+N),我认为这不是一个糟糕的近似,除非它的实现是幼稚的 第一个问题的答案很简单:它是C(n,r)
,我们从一组大小n
中选择r
项的所有组合。公式包括:
C(n,r) = n! / (r! (n-r)!)
选择第i个组合而不计算所有其他组合的能力取决于是否具有将组合编号i与组合关联的编码。这将是更具挑战性的,需要更多的思考
(编辑)
仔细考虑这个问题后,Python中的解决方案如下所示:
from math import factorial
def combination(n,r):
return factorial(n) / (factorial(r) * factorial(n-r))
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def showComb(n,r,i,a):
if r < 1:
return ""
rr = r-1
nn = max(n-1,rr)
lasti = i
i -= combination(nn,rr)
j = 0
while i > 0:
j += 1
nn = max(nn-1,1)
rr = min(rr,nn) # corrected this line in second edit
lasti = i
i -= combination(nn,rr)
return a[j] + showComb(n-j-1,r-1,lasti,a[(j+1):])
for i in range(10):
print(showComb(5,3,i+1,alphabet))
。。。这证实了这120个例子都是正确的
我还没有精确计算时间复杂度,但是对
showComb()
的调用次数将是r
,而while
循环将执行n
次或更少。因此,在这个问题的术语中,如果我们假设factorial()
函数可以在恒定时间内计算,我非常确定复杂性将小于O(M+N),我认为这不是一个糟糕的近似,除非它的实现是幼稚的 同意第一部分很简单,用你选择的语言表达类似的等式
x=12
y=5
z=1
base=1
until [[ $z -gt y ]]
do
base=`echo $x $z $base|awk '{print ($1/$2) * $3}'`
x=`expr $x - 1`
z=`expr $z + 1`
echo base:$base
done
echo $base
上面的示例使用了12个项目,以5个为一组,用于792个组合
做你问题的第二部分。。。我只是在想,但它不是直截了当的。同意第一部分很简单,用你选择的语言表达类似的等式
x=12
y=5
z=1
base=1
until [[ $z -gt y ]]
do
base=`echo $x $z $base|awk '{print ($1/$2) * $3}'`
x=`expr $x - 1`
z=`expr $z + 1`
echo base:$base
done
echo $base
上面的示例使用了12个项目,以5个为一组,用于792个组合
做你问题的第二部分。。。我只是在想,但它不是直截了当的。看起来很棒!我一直在修改您的解决方案,并尝试将I范围(120):打印(showComb(10,3,I+1,字母表))的循环更改为
。但它会产生错误的组合和崩溃。@dragonroot:谢谢您的测试!是的,当n-r
大于2时,代码中出现了一个bug。我已经在上面编辑的答案中更正了。看起来很棒!我一直在修改您的解决方案,并尝试将I范围(120):打印(showComb(10,3,I+1,字母表))的循环更改为。但它会产生错误的组合和崩溃。@dragonroot:谢谢您的测试!是的,当n-r
大于2时,代码中出现了一个bug。我已经在上面编辑的答案中更正了它。