生成大小为 1 到 n 的所有组合(位集)

Posted

技术标签:

【中文标题】生成大小为 1 到 n 的所有组合(位集)【英文标题】:Generating all combinations of size 1 to n (bitsets) 【发布时间】:2022-01-03 23:31:18 【问题描述】:

有很多关于堆栈溢出的快速方法可以生成大小为 k 的位集的所有组合。

例如:

combos(4,3) = 1110,1101,1011,0111

但是,有没有一种快速的方法来计算尺寸 1 到 n 的所有组合?

例如:

allCombos(4) = 

  1: 0001, 0010, 0100, 1000
  2: 0011, 0101, 1001, 0110, 1010, 1100
  3: 0111, 1011, 1101, 1110
  4: 1111

当然,我可以只为从 1 到 4 的 i 调用 combos(4, i)。但是,我想利用以下事实:

对于combos(4, i) 中的每个位集X,我们可以将位集X 中的一位从0 设置为1。

例如,0011combos(4,2) 中,它会在 combos(4,3) 中生成 1011, 0111,因为第一个和第二个最高有效位是 0。

编辑:这是我目前的完成方式:

def combos(set_, k):
    return map(sum, itertools.combinations(set_, k)) # take combos of 1, 2, 4, 8 ... and the sums to get bitset back

def allCombos(n):
    ret = 
    bitset = set([2**i for i in range(n)]) # generates 1, 2, 4, 8 ...
    for k in range(1,n+1):
        ret[k] = combos(bitset, k)
    return k

【问题讨论】:

老实说,我不认为你的“捷径”特别有效。对于“列表n”中的任何特定元素,“列表n-1”中的n 元素可以设置一个位来给出该元素。如果你使用itertools.combinations,它真的很高效。 itertools.combinations 需要一个集合作为输入。我的输入将是一个整数(一个位集)。现在,我必须将我的位集转换为实际的 Python 集,调用 itertools.combinations,然后将该集转换回位集。效率太低了。 ***.com/questions/70119046/… @martineau。我不认为这是重复的。此用户未尝试创建子集。他想要设置这么多位的数字,这是一个稍微不同的问题。 “快速方式”是相当主观的 - 您当前的方法有多快?当前方法的代码是什么样的? 【参考方案1】:

正如 Frank Yellin 指出的那样,您的“捷径”可能并没有那么有用。我认为您可以稍微缩短此计算时间的唯一方法是认识到,如果我们翻转combos(n,i) 中每个位集中的每个位,我们将得到位集combos(n,n-i)。您可以创建一个非常简单且快速的函数,该函数将接收一组位集并为每个返回一个具有相反位集的集。例如,如果给定combos(4,1),即0001,0010,0100,1000,它将输出1110,1101,1011,0111,即combos(4,3)。这会将您的运行时间减少大约一半。

【讨论】:

以上是关于生成大小为 1 到 n 的所有组合(位集)的主要内容,如果未能解决你的问题,请参考以下文章

R从n个元素的字符向量中生成大小为m的所有可能组合[重复]

如何检查整数是否在给定范围的集合中? [关闭]

生成一个矩阵,其中包含取自 n 个向量的元素的所有组合

从数组(Java)中获取所有大小 n 组合的算法? [关闭]

markdown 打印给定大小为n的数组中r元素的所有可能组合

使用递归和回溯生成所有可能的组合