给定k
第一个n
自然数的组合,出于某种原因,我需要在返回的那些组合中找到这种组合的位置itertools.combination(range(1,n),k)
(原因是这样我可以使用 alist
而不是 adict
来访问与每个组合关联的值,知道组合)。
由于itertools
以常规模式产生它的组合,因此可以做到这一点(而且我还找到了一个简洁的算法),但我正在寻找一种更快/更自然的方式,我可能会忽略它。
顺便说一下,这是我的解决方案:
def find_idx(comb,n):
k=len(comb)
idx=0
last_c=0
for c in comb:
#idx+=sum(nck(n-2-x,k-1) for x in range(c-last_c-1)) # a little faster without nck caching
idx+=nck(n-1,k)-nck(n-c+last_c,k) # more elegant (thanks to Ray), faster with nck caching
n-=c-last_c
k-=1
last_c=c
return idx
其中nck
返回n,k 的二项式系数。
例如:
comb=list(itertools.combinations(range(1,14),6))[654] #pick the 654th combination
find_idx(comb,14) # -> 654
这是一个等效但可能涉及较少的版本(实际上我从下一个派生了前一个)。我将组合的整数c
视为二进制数字中 1 的位置,我在解析 0/1 时构建了一个二叉树,并且在解析过程中发现了索引递增的规则模式:
def find_idx(comb,n):
k=len(comb)
b=bin(sum(1<<(x-1) for x in comb))[2:]
idx=0
for s in b[::-1]:
if s=='0':
idx+=nck(n-2,k-1)
else:
k-=1
n-=1
return idx