【问题标题】:Extract all possible ordered sub-sets提取所有可能的有序子集
【发布时间】:2014-02-26 16:36:24
【问题描述】:

我有一组元素,我想从中提取 ordered 子集。我所说的ordered 子集的意思是我不能在集合内切换元素。我举了三个例子来说明我是如何解决这个问题的。

  • 如何递归提取这些子集?
  • 你有什么伪代码吗?
  • { . } = 子集

示例 1

S = {f1,f2,f3} 是一个由3 个元素组成的集合。我想提取所有可能的有序子集如下:

-{f1},{f2},{f3} // {f1} is a subset, {f2} is a subset etc.
-{f1,f2},{f3} // {f1,f2} form a subset and {f3} is also a subset
-{f1},{f2,f3} // {f1} is a subset and {f2,f3} form a subset 

示例 2

S = {f1,f2,f3,f4}4个元素组成。

可能的有序子集:

-{f1},{f2},{f3},{f4}
-{f1,f2},{f3,f4}
-{f1},{f2,f3},{f4}
-{f1},{f2},{f3,f4}
-{f1,f2,f3}{f4}
-{f1},{f2,f3,f4}
-{f1,f2},{f3},{f4}
-{f1,f2,f3,f4}

示例 3

S = {f1,f2,f3,f4,f5}5个元素组成。

可能的有序子集:

-{f1},{f2},{f3},{f4},{f5}
-{f1,f2},{f3},{f4},{f5}
-{f1},{f2,f3},{f4},{f5}
-{f1},{f2},{f3,f4},{f5}
-{f1},{f2},{f3},{f4,f5}
-{f1,f2},{f3,f4},{f5}
-{f1},{f2,f3},{f4,f5}
-{f1,f2,f3},{f4,f5}
-{f1,f2,f3},{f4},{f5}
-{f1},{f2,f3,f4},{f5}
-{f1},{f2},{f3,f4,f5}
-{f1,f2},{f3,f4,f5}
-{f1,f2,f3,f4}{f5}
-{f1},{f2,f3,f4,f5}
- etc...

【问题讨论】:

  • 你试过什么?添加新元素时可以做哪些新子集?
  • 您错过了 4 个元素和 5 个元素的一个子集。 (提示:解决方案数量为2**(n-1))。

标签: c++ algorithm recursion combinations subset


【解决方案1】:

如果数组包含该集合,请修改数组,使每个元素之间有一个空格。该空间保留用于分区。采用任何命名约定。 0 表示没有分区,而 1 表示分区。现在遍历数组以递归方式在分区中添加10。可以生成所有可能的组合。

示例1

S = {f1,f2,f3}
S'= {f1,0,f2,0,f3}

所以子集将是:

{f1,0,f2,0,f3}, {f1,0,f2,1,f3}, {f1,1,f2,0,f3}, {f1,1,f2,1,f3}

等同于:

{f1,f2,f3}, {{f1,f2},{f3}}, {{f1},{f2,f3}}, {{f1},{f2},{f3}}

如果不希望原始集合出现在所有子集的集合中,只要不考虑每个分区包含0的状态即可。

【讨论】:

  • 只是为了扩展,不管你怎么做,你真正寻找的是所有可能的分区排列。任何给定列表中的分区数 > 0 为 L-1。有很多算法可以得到所有可能的排列,en.wikipedia.org/wiki/…
  • @Rikayan 我有一个问题。 Now traverse through the array to recursively add 1 or 0 in the partition 到底是什么意思
  • @Ryan 很有趣,我明白了。我现在正在编码。你的想法很简单
【解决方案2】:

假设 set S = {a,b,c,d} 包含 4 个元素。所有的子集都可以通过将 2 ^ n - 1 写入二进制和随后的减法来生成。

a b c d

1 1 1 1 => (a b c d)

1 1 1 0 => (a b c)(d)

1 1 0 1 => (a b d)(c) //逻辑是将所有的 1 组合在一起

1 1 0 0 => (a b) 现在 0 0 可以进一步分解为 (1 1) => (c d) , (1 0) => (c)(d)

1 0 1 1 => (a c d)(b)

1 0 1 0 => (a c) 现在 0 0 可以进一步分解为 (1 1) => (b d ), (1 0 ) => (b)(d)

1 0 0 1 => (a d) 步骤同上

1 0 0 0 => (a) 现在剩下 3 个零,我们有 b c d 作为 3 个集合,现在我们可以从 1 1 1 重新开始,然后转到 1 1 0 等等。

通过这种方式,我们能够生成所有子集。

【讨论】:

  • 感谢您的提议。但我不能像你在 8 行中提到的那样拥有 (ac) 或 (ad)
  • 如您所见,我无法切换数组中的元素位置。
猜你喜欢
  • 2012-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多