【问题标题】:Generating all combinations of size 1 to n (bitsets)生成大小为 1 到 n 的所有组合(位集)
【发布时间】: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,然后将该集转换回位集。效率太低了。
  • @martineau。我不认为这是重复的。此用户未尝试创建子集。他想要设置这么多位的数字,这是一个稍微不同的问题。
  • “快速方式”是相当主观的 - 您当前的方法有多快?当前方法的代码是什么样的?

标签: python combinations bitset


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-16
    相关资源
    最近更新 更多