【问题标题】:Obtaining the powerset of set with subsets of a certain size in Java在Java中获得具有一定大小子集的集合的幂集
【发布时间】:2015-10-03 02:54:36
【问题描述】:

我正在尝试找到一种有效的方式来生成具有特定大小 k 的子集的集合的幂集。我已经找到了如何在一个范围内生成所有 powerset 和 powerset 的答案,但是如果我只想要一个特定的大小,我不确定该怎么做。

谢谢!

【问题讨论】:

  • 你有没有试过这样做?也许您的实施效率低下?
  • 集合有多少个元素?
  • @Sesame,我目前正在使用一种方法来生成整个 powerset,然后遍历它并删除与我想要的长度不匹配的子集。
  • 通常情况下的“公式”是2^S = flatten([[x U Y for Y in 2^(S-{x})] for x in S])。您想要大小为n 的子集,因此您希望每个Y 的大小为n-1。因此,只需采用现有实现并向函数添加额外的大小参数,并在递归调用时使用size-1
  • @user3386109,该集合有 2 到 31 个元素。我想生成长度为 3 的子集。

标签: java algorithm set big-o


【解决方案1】:

创建一个包含集合元素的列表。

创建仅包含 1 和 0 的第二个列表,其中

  • 列表中的元素总数等于集合中的元素数
  • 列表中1的个数等于k

对于第二个列表的每个排列,子集由第一个列表中的元素组成,这些元素在第二个列表中的对应条目为 1。

【讨论】:

  • 不是排列,而是组合。集合中的元素没有顺序。
  • @someguy 创建一个列表,而不是一个集合,并计算列表的所有排列。
  • 底层数据结构不相关。您想要大小为k 的所有组合,而不是排列。例如,集合 {x, y} 只有一个大小为 2 的子集。您的方法将返回两个子集,就好像 {x, y} 和 {y, x} 不相等。
  • @someguy 我想我们不同意排列的定义。例如,我定义了{0,1,1} as {{0,1,1}, {1,0,1}, {1,1,0}} 的排列,请参阅this answer,了解一种计算数组排列而不重复的方法。
  • 排列的定义不能有不同意见。这是一个数学概念!你的例子是有缺陷的,因为那个“集合”实际上不是一个集合。元素必须是唯一的。如果是的话,你会发现实际上有 6 种不同的排列。然而,就像我说的,我们感兴趣的是不同的组合,而不是排列。请阅读这个小条目:en.wikipedia.org/wiki/Power_set#Relation_to_binomial_theorem。这是基本集合/概率论。
【解决方案2】:

您可以使用简单的回溯来执行此操作。您只需检查每个元素,然后选择该元素是否包含在您的子集中。同时,您可以跟踪您正在尝试构建的当前子集 (current_subset) 以及您仍然可以选择多少元素 (k)。示例实现:

static <E> void backtrack(int index, int k, Deque<E> current_subset,
                          List<E> elements) 
{
    if (k == 0) {
        System.out.println(current_subset);
        return;
    }
    if (index == elements.size())
        return;
    current_subset.push(elements.get(index));
    backtrack(index + 1, k - 1, current_subset, elements);
    current_subset.pop();
    backtrack(index + 1, k, current_subset, elements);
}

backtrack(0, 2, new ArrayDeque<Integer>(), 
          Arrays.asList(new Integer[]{0, 1, 2, 3, 4}));
/*
[1, 0]
[2, 0]
[3, 0]
[4, 0]
[2, 1]
[3, 1]
[4, 1]
[3, 2]
[4, 2]
*/

请注意,如果您要保留子集,您可以将它们插入到某种结构中(例如 List),而不是打印它们。

【讨论】:

    【解决方案3】:

    这是通过将集合转换为列表并遍历所有可能的索引组合来实现的。

    static <E> Set<Set<E>> subsets(Set<E> set, int n) {
        if (n < 0)
            throw new IllegalArgumentException();
        Set<Set<E>> temp = new HashSet<>();
        int size = set.size();
        if (n > size)
            return temp;
        List<E> list = new ArrayList<>(set);
        int[] indices = new int[n];
        for (int i = 0; i < n; i++)
            indices[i] = i;
        while (true) {
            Set<E> s = new HashSet<>();
            for (int i : indices)
                s.add(list.get(i));
            temp.add(s);
            int r = n - 1;
            for (int m = size; r >= 0 && indices[r] == --m; r--);
            if (r == -1)
                return temp;
            for (int c = indices[r]; r < n;)
                indices[r++] = ++c;
        }
    }
    

    【讨论】:

      【解决方案4】:

      试试这个生成集合的幂集:

      import java.util.ArrayList;
      import java.util.HashSet;
      import java.util.List;
      import java.util.Set;
      
      public class GeneratePowerSet {
      
          public static <T> Set<Set<T>> powerSet(Set<T> originalSet) {
              Set<Set<T>> sets = new HashSet<>();
              if (originalSet.isEmpty()) {
                  sets.add(new HashSet<T>());
                  return sets;
              }
              List<T> list = new ArrayList<>(originalSet);
              T head = list.get(0);
              Set<T> rest = new HashSet<>(list.subList(1, list.size()));
              for (Set<T> set : powerSet(rest)) {
                  Set<T> newSet = new HashSet<>();
                  newSet.add(head);
                  newSet.addAll(set);
                  sets.add(newSet);
                  sets.add(set);
              }
              return sets;
          }
      
          public static void main(String args[]) {
              Set<Integer> mySet = new HashSet<Integer>();
              mySet.add(1);
              mySet.add(2);
              mySet.add(3);
              mySet.add(4);
              for (Set<Integer> s : powerSet(mySet)) {
                  System.out.println(s);
              }
          }
      
      }
      

      欲了解更多信息,请访问https://github.com/m-vahidalizadeh/foundations/blob/master/src/algorithms/GeneratePowerSet.java。我希望它有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-10
        • 2018-06-05
        • 1970-01-01
        相关资源
        最近更新 更多