求取一個集合中的所有子集
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的補全的過程
//後續複習的時候會繼續補充說明