我正在尝试找到一种高效的方法来生成一个集合的幂集,其中包含特定大小k的子集。我已经找到了如何生成所有幂集和范围内的幂集的答案,但是如果我只想要一个确定大小的幂集,我不确定该怎么做。谢谢!
k
的组合而非排列。例如,集合 {x, y} 只有一个大小为 2 的子集。您的方法会返回两个子集,好像 {x, y} 和 {y, x} 是不相等的一样。 - someguy{0,1,1}
的排列定义为 {{0,1,1}, {1,0,1}, {1,1,0}}
。请参见此答案,其中提供了一种计算数组排列而没有重复项的方法。 - user3386109这个方法通过将集合转换为列表,并迭代所有可能的索引组合来实现。
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;
}
}
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
)中,而不是打印它们。尝试这个方法以生成一个集合的幂集:
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。希望能对您有所帮助。
2^S = flatten([[x U Y for Y in 2^(S-{x})] for x in S])
。您想要大小为n
的子集,因此您希望每个Y
的大小为n-1
。因此,只需使用现有实现并向函数添加额外的大小参数,并在递归调用时使用size-1
即可。 - Alex Hall