求取一个集合中的所有子集
package 算法学习;
import java.util.HashSet;
import java.util.Set;
/**
* Page Description:
* User: Yelihu
* Date: 2019-03-02
* Time: 下午 3:02
* Function:
*/
public class 增量迭代 {
private static int[] array = {1,2,0,4};
private static Set<Set<Integer>> handler(int[] array,int n){
return getSubSetCore(array,n,n-1);
}
private static Set<Set<Integer>> getSubSetCore(int[] array,int n,int cur){
//创建一个集合存放原来集合+加上增量集合
Set<Set<Integer>> newSet = new HashSet<>();
if(cur==0){
Set<Integer> nullSet = new HashSet<>();
Set<Integer> firstSet = new HashSet<>();
firstSet.add(array[0]);
newSet.add(firstSet);
newSet.add(nullSet);
return newSet;
}
//获取到原来集合
Set<Set<Integer>> oldSet = getSubSetCore(array,n,cur-1);
//从老集合中获取到一个个数字,拷贝出来加入新的集合
for (Set<Integer> set: oldSet) {
newSet.add(set);
Set<Integer> clone = (Set<Integer>) ((HashSet)set).clone();
clone.add(array[cur]);
newSet.add(clone);
}
return newSet;
}
public static void main(String[] args) {
Set<Set<Integer>> sets = handler(array,array.length);
System.out.println(sets);
}
}
带注释解析版本
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
int[] A = {1,2,3};
System.out.println(A.length);
Set<Set<Integer>> subSets = new Main().getSubset3(A,A.length);
System.out.println(subSets);
}
private Set<Set<Integer>> getSubset3(int[] A,int n){
return getSubsets3Core(A,n,n-1);
}
/**
* 递归增量构造法
* @param A
* @param n
* @param cur
* @return
*/
private Set<Set<Integer>> getSubsets3Core(int[] A,int n,int cur ){
Set<Set<Integer>> newSet = new HashSet<>();
//如果cur==0,那么在处理第一个元素
if(cur==0){
//空集
Set<Integer> nil = new HashSet<>();
//包含第一个元素的集合
Set<Integer> first = new HashSet<>();
first.add(A[0]);
newSet.add(nil);
newSet.add(first);
return newSet;
}
Set<Set<Integer>> oldSet = getSubsets3Core(A,n,cur-1);
for (Set<Integer> set:oldSet) {
//对于每个子集来说,cur这个元素,可以加入也可以不加入
//set就是oldSet里面的一个子集,把它取出来,放在newSet里面,比如说是[1]
newSet.add(set);
//克隆之前取出的子集元素set,叫做clone,也就是说新的一个set,名字叫clone,内容是[1]
Set<Integer> clone = (Set<Integer>) ((HashSet)set).clone();
//clone加入增量元素,这个元素从数组中取出,递归每回溯一次,就会加入新的元素
//这个时候clone的内容是,[1,2]
clone.add(A[cur]);
//向newSet里面添加clone,整个过程,newSet的添加顺序是,[空集],[2],[1][1,2].
newSet.add(clone);
}
return newSet;
}
}
注意点:在java中的set,空集加入一个元素之后,就是元素本身,比如我用null表示空集,原来一个set是[null],add了一个2之后,实际上这个set就变成了[2],而不是[null,2]。
//在这个过程中,作为全部子集的集合newSet是如何一步步的补全的,我们可以把它看作一棵类似二叉树的过程,每个节点在下一次getSubSetCore函数调用的时候,都会向下产生两个分支,一个是节点原来的样子,变成这个节点的一个子节点,另一个是加上从数组中取出来的新的元素之后的节点。
如下图所示,左边我标注了是在取出数组第几个,右边表示的三次调用getSubSetCore函数之后,newSet的补全的过程
//后续复习的时候会继续补充说明