子集数量=2 ^ n = 1 (空集) + (2^n-1) (非空子集)
算法原理:每个元素有两种处理方式,取或不取,共2 ^ n 种组合
递归算法
boolean[] done 为标志数组,表明对应位置元素取或不取
public static void recursion(int[] root) {
Objects.requireNonNull(root);
boolean[] done=new boolean[root.length];
recursion(root,0,done);
}
public static void recursion(int[] root,int index,boolean[] done) {
if(root.length>index) {
//保留root[index]
done[index]=true;
recursion(root,index+1,done);
//复原标志数组
done[index]=false;
//不保留root[index]
recursion(root,index+1,done);
}else {
//打印
StringBuffer buffer=new StringBuffer();
buffer.append("[");
for(int i=0;i<done.length;i++) {
if(done[i]) {
buffer.append(root[i]+",");
}
}
if(buffer.length()>1) {
buffer.deleteCharAt(buffer.length()-1);
}
buffer.append("]");
System.out.println(buffer);
}
}
测试
int [] a=new int[] {1,2,3,4};
recursion(a);
输出:
[1,2,3,4]
[1,2,3]
[1,2,4]
[1,2]
[1,3,4]
[1,3]
[1,4]
[1]
[2,3,4]
[2,3]
[2,4]
[2]
[3,4]
[3]
[4]
[]
迭代法
共2 ^ n 种组合,对第k个组合,将k看作二进制数,那么它的对应位0,1就表明对应元素取或不取
class ComItr implements Iterator<List<Integer>>{
private long title;
private long count=0;
public int[]root;
public ComItr(int[] root) {
this.root=root;
title=1<<root.length;
}
public boolean hasNext() {
return title>count;
}
public List<Integer> next() {
ArrayList<Integer> list=new ArrayList<Integer>() ;
for(int i=0;i<root.length;i++) {
if(((1<<i)&count)!=0) {
list.add(root[i]);
}
}
count++;
return list;
}
}
测试
int [] a=new int[] {1,2,3,4};
ComItr itr=new ComItr(a);
while(itr.hasNext()) {
System.out.println(itr.next());
}
[]
[1]
[2]
[1, 2]
[3]
[1, 3]
[2, 3]
[1, 2, 3]
[4]
[1, 4]
[2, 4]
[1, 2, 4]
[3, 4]
[1, 3, 4]
[2, 3, 4]
[1, 2, 3, 4]