Cracking the coding interview--Q8.3

题目

原文:

Write a method that returns all subsets of a set.

译文:

写一个方法返回一个集合的所有子集合。

解答

对于一个集合,它的总共子集数为2^n(包括空集)。对于S(5)={1,2,3,4,5},则S(5)的子集数可以写为:5与S(4)的子集的组合+S(4)的子集,得递归算法如下:

	public static LinkedList<LinkedList<Integer>> recursionSubSet(int[] set,int n,int index){
		LinkedList<LinkedList<Integer>> subsets=new LinkedList<LinkedList<Integer>>();
		if(index==n){   //judge the end
			LinkedList<Integer> subset=new LinkedList<Integer>();
			subsets.add(subset);
		}else{
			LinkedList<LinkedList<Integer>> part=recursionSubSet(set,n,index+1);
			int v=set[index];
			for(int i=0;i<part.size();i++){
				LinkedList<Integer> subset=part.get(i);
				subsets.add(subset);
				LinkedList<Integer> newsubset = new LinkedList<Integer>();
				for(Integer entry:subset){
					newsubset.add(entry);
				}
				newsubset.add(v);
				subsets.add(newsubset);
			}
		}
		return subsets;
	}
另外,对于一个集合的任意一个子集,可以看做这个集合本身的每个元素是否出现而形成的一个序列,又因为子集总数为2^n,所以可以通过二进制来做标记,如:集合(1,2,3),当集合被标记为(0,0,0)是,则为空集;子集(1,3),不是2没出现,二进制位0,1和3出现则为1;所以集合(1,2,3)的子集可以用二进制000~111,8(2^3)个二进制标记,遍历每个二进制的每位,判断是否出现,再添加进对应的子集即可,代码如下:

	public static LinkedList<LinkedList<Integer>> binarySubSet(int[] set,int n){
		LinkedList<LinkedList<Integer>> subsets=new LinkedList<LinkedList<Integer>>();
		int max=1<<n;   //the number of total subset
		for(int i=0;i<max;++i){
			LinkedList<Integer> subset=new LinkedList<Integer>();
			int index=0;
			int j=i;
			while(j>0){
				if((j&1)==1){  //judge the byte
					subset.add(set[index]);
				}
				j>>=1;
				++index;
			}
			subsets.add(subset);
		}
		return subsets;
	}

完整代码如下:

import java.util.LinkedList;
import java.util.Iterator;

class Q8_3{
	//recursion
	//n is the length of the set, index act as marking, at the beginning of 0
	public static LinkedList<LinkedList<Integer>> recursionSubSet(int[] set,int n,int index){
		LinkedList<LinkedList<Integer>> subsets=new LinkedList<LinkedList<Integer>>();
		if(index==n){   //judge the end
			LinkedList<Integer> subset=new LinkedList<Integer>();
			subsets.add(subset);
		}else{
			LinkedList<LinkedList<Integer>> part=recursionSubSet(set,n,index+1);
			int v=set[index];
			for(int i=0;i<part.size();i++){
				LinkedList<Integer> subset=part.get(i);
				subsets.add(subset);
				LinkedList<Integer> newsubset = new LinkedList<Integer>();
				for(Integer entry:subset){
					newsubset.add(entry);
				}
				newsubset.add(v);
				subsets.add(newsubset);
			}
		}
		return subsets;
	}
	//binary
	//n is the length of the set
	public static LinkedList<LinkedList<Integer>> binarySubSet(int[] set,int n){
		LinkedList<LinkedList<Integer>> subsets=new LinkedList<LinkedList<Integer>>();
		int max=1<<n;   //the number of total subset
		for(int i=0;i<max;++i){
			LinkedList<Integer> subset=new LinkedList<Integer>();
			int index=0;
			int j=i;
			while(j>0){
				if((j&1)==1){  //judge the byte
					subset.add(set[index]);
				}
				j>>=1;
				++index;
			}
			subsets.add(subset);
		}
		return subsets;
	}

	public static void main(String[] args){
		int[] dataset={1,2,3,4};
		Iterator<LinkedList<Integer>> it=recursionSubSet(dataset,dataset.length,0).iterator();
		while(it.hasNext()){
			LinkedList<Integer> set=it.next();
			System.out.println(set);
		}
		System.out.println("");
		Iterator<LinkedList<Integer>> it1=binarySubSet(dataset,dataset.length).iterator();
		while(it1.hasNext()){
			LinkedList<Integer> set=it1.next();
			System.out.println(set);
		}
	}
}

---EOF---

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值