如何找到指定长度的所有子集?
How to find all subsets of a specified length?
我在 previous question 中问过这个问题。我想找到指定长度的所有子集。
Damien 用 C++ 给我写了一个 nice answer,我正在尝试转换它,但没有成功。这是我的尝试:
import java.util.*;
public class Subset {
void getSubsetAux(ArrayList<ArrayList<Integer>> s, int n, int k, int i,
ArrayList<Integer> dom, ArrayList<Integer> cs) {
if(n<k) return;
if(k == 0) {
s.add(cs);
return;
}
getSubsetAux(s, n-1, k, i+1, dom, cs);
cs.add(dom.get(i));
getSubsetAux(s, n-1, k-1, i+1, dom, cs);
cs.remove(cs.size() -1);
}
void getSubset(ArrayList<ArrayList<Integer>> s, int l, ArrayList<Integer> dom) {
ArrayList<Integer> cs = new ArrayList<>();
getSubsetAux(s, dom.size(), l, 0, dom, cs);
}
public void print(ArrayList<ArrayList<Integer>> l) {
for (ArrayList<Integer> el: l) {
System.out.println(el);
}
}
public void run(String[] args) {
ArrayList<Integer> dom = new ArrayList<>(Arrays.asList(1,2,3,4,5));
ArrayList<ArrayList<Integer>> ret = new ArrayList<ArrayList<Integer>>();
getSubset(ret, 3, dom);
print(ret);
}
public static void main(String [] args) {
Subset s = new Subset();
s.run(args);
}
}
输出:
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
预期输出:(不一定是这个顺序)
[3, 4, 5]
[2, 4, 5]
[2, 3, 5]
[2, 3, 4]
[1, 4, 5]
[1, 3, 5]
[1, 3, 4]
[1, 2, 5]
[1, 2, 4]
[1, 2, 3]
我认为这与我不了解 Java
中的输出参数有关
如果您只对结果而不是算法本身感兴趣,您可以使用像 CombinatoricsLib, Guava or Apache Commons 这样的库:
使用 CombinatoricsLib,代码可以像这样简单:
List<Integer> dom = Arrays.asList(1,2,3,4,5);
Generator.combination(dom)
.simple(3)
.stream()
.forEach(System.out::println);
得到输出:
[1, 2, 3]
[1, 2, 4]
[1, 2, 5]
[1, 3, 4]
[1, 3, 5]
[1, 4, 5]
[2, 3, 4]
[2, 3, 5]
[2, 4, 5]
[3, 4, 5]
但是如果你有兴趣自己实现算法,可能这个post是神读:https://www.baeldung.com/java-combinations-algorithm
如here所述,
您正在多次向外部列表添加对同一内部 ArrayList 的引用。因此,当您更改内部列表时,您会在所有内部列表中看到它。
要获得您想要的结果,您应该创建一个新的临时内部列表:
if(k == 0) {
ArrayList<Integer> temp = new ArrayList<Integer>(cs);
s.add(temp);
return;
}
我在 previous question 中问过这个问题。我想找到指定长度的所有子集。
Damien 用 C++ 给我写了一个 nice answer,我正在尝试转换它,但没有成功。这是我的尝试:
import java.util.*;
public class Subset {
void getSubsetAux(ArrayList<ArrayList<Integer>> s, int n, int k, int i,
ArrayList<Integer> dom, ArrayList<Integer> cs) {
if(n<k) return;
if(k == 0) {
s.add(cs);
return;
}
getSubsetAux(s, n-1, k, i+1, dom, cs);
cs.add(dom.get(i));
getSubsetAux(s, n-1, k-1, i+1, dom, cs);
cs.remove(cs.size() -1);
}
void getSubset(ArrayList<ArrayList<Integer>> s, int l, ArrayList<Integer> dom) {
ArrayList<Integer> cs = new ArrayList<>();
getSubsetAux(s, dom.size(), l, 0, dom, cs);
}
public void print(ArrayList<ArrayList<Integer>> l) {
for (ArrayList<Integer> el: l) {
System.out.println(el);
}
}
public void run(String[] args) {
ArrayList<Integer> dom = new ArrayList<>(Arrays.asList(1,2,3,4,5));
ArrayList<ArrayList<Integer>> ret = new ArrayList<ArrayList<Integer>>();
getSubset(ret, 3, dom);
print(ret);
}
public static void main(String [] args) {
Subset s = new Subset();
s.run(args);
}
}
输出:
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
预期输出:(不一定是这个顺序)
[3, 4, 5]
[2, 4, 5]
[2, 3, 5]
[2, 3, 4]
[1, 4, 5]
[1, 3, 5]
[1, 3, 4]
[1, 2, 5]
[1, 2, 4]
[1, 2, 3]
我认为这与我不了解 Java
中的输出参数有关如果您只对结果而不是算法本身感兴趣,您可以使用像 CombinatoricsLib, Guava or Apache Commons 这样的库:
使用 CombinatoricsLib,代码可以像这样简单:
List<Integer> dom = Arrays.asList(1,2,3,4,5);
Generator.combination(dom)
.simple(3)
.stream()
.forEach(System.out::println);
得到输出:
[1, 2, 3]
[1, 2, 4]
[1, 2, 5]
[1, 3, 4]
[1, 3, 5]
[1, 4, 5]
[2, 3, 4]
[2, 3, 5]
[2, 4, 5]
[3, 4, 5]
但是如果你有兴趣自己实现算法,可能这个post是神读:https://www.baeldung.com/java-combinations-algorithm
如here所述, 您正在多次向外部列表添加对同一内部 ArrayList 的引用。因此,当您更改内部列表时,您会在所有内部列表中看到它。
要获得您想要的结果,您应该创建一个新的临时内部列表:
if(k == 0) {
ArrayList<Integer> temp = new ArrayList<Integer>(cs);
s.add(temp);
return;
}