生成集合中的所有“唯一”子集(不是powerset)

时间:2011-12-27 10:50:30

标签: ruby erlang set subset powerset

假设我们有一个包含几个子集的集S

- [a,b,c]
- [a,b]
- [c]
- [d,e,f]
- [d,f]
- [e]

我们还要说S包含六个独特元素:a, b, c, d, ef

我们怎样才能找到S的所有可能子集,其中只包含S的每个唯一元素一次?

函数/方法的结果应该是这样的:

  1. [[a,b,c], [d,e,f]];
  2. [[a,b,c], [d,f], [e]];
  3. [[a,b], [c], [d,e,f]];
  4. [[a,b], [c], [d,f], [e]].
  5. 有没有最佳实践或任何标准方法来实现这一目标?

    对于伪代码,Ruby或Erlang示例,我将不胜感激。

4 个答案:

答案 0 :(得分:3)

听起来你正在寻找的是一组/数组的partitions

这样做的一种方法是递归地:

  • 1个元素数组[x]只有一个分区
  • 如果x是x = [head] + tail形式的数组,那么x的分区是通过获取尾部的每个分区并为每个可能的头部添加头来生成的。例如,如果我们从[2,1]的分区[[2,1]]生成[3,2,1]的分区,我们可以将3添加到[2,1]或作为单独的元素,它给了我们2个分区[[3,2,1]或[[2,1],[3]]的5 [1,2,3]

ruby​​实现看起来有点像

def partitions(x)
  if x.length == 1
   [[x]]
  else
    head, tail = x[0], x[1, x.length-1]
    partitions(tail).inject([]) do |result, tail_partition|
      result + partitions_by_adding_element(tail_partition, head)
    end
  end
end

def partitions_by_adding_element(partition, element)
  (0..partition.length).collect do |index_to_add_at|
    new_partition = partition.dup
    new_partition[index_to_add_at] = (new_partition[index_to_add_at] || []) + [element]
    new_partition
  end
end

答案 1 :(得分:1)

为什么不使用贪婪算法?

1)排序集S使用子集长度
下降 2)让我:= 0
3)将S [i]添加到解决方案中 4)找到S [j]其中j>我所包含的元素不在当前的解决方案中 5)如果你找不到4中描述的元素那么   5.a)明确的解决方案
  5.b)增加i
  5.c)如果我> | S |然后休息,找不到解决方案;(   5.d)转到3

修改
嗯,再读一遍你的帖子,得出你需要Best-First search的结论。您的问题实际上不是分区问题,因为您需要的内容也称为Change-making problem,但在后一种情况下,第一个解决方案被视为最佳解决方案 - 您实际上想要找到所有解决方案,这就是您的原因你应该采用最好的搜索策略方法吗?

答案 2 :(得分:0)

这似乎是一种经典的“回溯”练习。

  • #1:在eacother中订购你的套装,所以回溯不会给出解决方案两次。
  • #2:current_set = [],set_list = []
  • #3:循环遍历所有具有低于set_list中最后一个的订单标记的集合(或者如果set_list为空则为all)。我们称之为set_at_hand
  • #4:如果set_at_hand与current_set没有交集
  • #4 / true / 1:将其联合到current_set,同时添加到set_list。
  • #4 / true / 2:current_set完成? true:将set_list添加到正确解决方案列表中。 false:递归到#3
  • #4 / true / 3:从current_set和set_list
  • 中删除set_at_hand
  • #5:循环结束
  • #6:return

答案 3 :(得分:0)

生成所有子集

def allSubsets set
    combs=2**set.length
    subsets=[]
    for i in (0..combs) do
        subset=[]
        0.upto(set.length-1){|j| subset<<set[j] if i&(1<<j)!=0}
        subsets<<subset
    end
    subsets
end