【问题标题】:Generate all "without-replacement" subsets series生成所有“无替换”子集系列
【发布时间】:2018-11-26 23:05:58
【问题描述】:

我正在寻找一种方法来生成集合的所有可能子组合,其中每个元素最多可以使用一次。

例如,集合{1,2,3} 会产生

{{1},{2},{3}}
{{1},{2,3}}
{{1,2},{3}}
{{2},{1,3}}
{{1,2,3}}

伪代码提示会很棒。另外,如果有一个术语,或者适用的术语,我很想学习它。

【问题讨论】:

    标签: combinatorics pseudocode


    【解决方案1】:

    首先,几点建议。

    将集合分离为不相交的子集称为集合分区(WikipediaMathWorld)。

    编码集合分区的常用方法是restricted growth string

    set partitions 的数量是Bell number,并且增长很快:对于 20 个元素的 set,有 51,724,158,235,372 个 set partitions。


    以下是编码的工作原理。 按升序查看元素:1、2、3、4、...。 让c 是当前子集的数量,最初是0。 每当当前元素是其子集的最低元素时,我们为该集合分配数字c,然后将c 增加1。 无论如何,我们记下包含当前元素的子集的编号。

    从过程中可以看出,字符串的第一个元素将是0,并且每个下一个元素不大于迄今为止的最大值加一。因此得名“限制性增长字符串”。


    例如,考虑分区{1,3},{2,5},{4}

    元素1 是其子集中的最低元素,因此子集{1,3}0 标记。
    元素2 是其子集中的最低元素,因此子集{2,5}1 标记。
    元素 3 位于已由 0 标记的子集中。
    元素 4 是其子集中的最低元素,因此子集 {4}2 标记。
    元素 5 位于已被 1 标记的子集中。

    因此我们得到字符串01021。 字符串告诉我们:

    元素 1 在子集 0 中。
    元素 2 在子集 1 中。
    元素 3 在子集 0 中。
    元素 4 在子集 2 中。
    元素 5 在子集 1 中。


    为了从不同的角度感受它,这里是一个四元素集合的所有分区,以及相应的缩减增长字符串:

    0000      {1,2,3,4}
    0001      {1,2,3},{4}
    0010      {1,2,4},{3}
    0011      {1,2},{3,4}
    0012      {1,2},{3},{4}
    0100      {1,3,4},{2}
    0101      {1,3},{2,4}
    0102      {1,3},{2},{4}
    0110      {1,4},{2,3}
    0111      {1},{2,3,4}
    0112      {1},{2,3},{4}
    0120      {1,4},{2},{3}
    0121      {1},{2,4},{3}
    0122      {1},{2},{3,4}
    0123      {1},{2},{3},{4}
    

    至于伪代码,生成所有此类字符串相对简单。 我们以递归方式进行。 保持c 的值,将从0c 的每个数字分配到当前位置,并且对于每个这样的选择,递归地构造字符串的其余部分。 也可以懒惰地生成它们,从一个全为零的字符串开始,然后反复查找按字典顺序排列的下一个这样的字符串,类似于 next_permutation 用于 list all permutations 的方式。

    最后,如果您想看到更多内容(以及提到的next 功能),这里有一点自我推销。 最近,我们在我的大学做了一个学习项目,要求学生以合理的效率实现组合对象的各种功能。 Here 是我们得到的限制增长字符串的部分;我链接了描述英文功能的标题部分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多