大约两个月前一位朋友问我一道他同事的面试题目:一个含有无重复元素的集合,找出它所有的子集。例如{1,2}的所有集合是{}, {1}, {2}, {1, 2}.
当时我预料到了这道题目的算法时间复杂度为O(2^n), 但是并没有写出代码来。前两天无意间又试着做了一下这道题目,然后接受查找的资料,原来这是一个专门的算法问题。学名为powerset.
代码如下:
1 /* 2 * 该算法的基本原理是:将集合分成前后两个部分: 3 * 前一部分是已经固定了的,后一部分为即将固定的, 4 * 然后将即将固定的添加到已经固定的集合的后面。 5 * 然后采用递归的方式,欲求{1,n-1},必先求{2, n-2}, 6 * 之后仿效类推,直到先求出{n-1, 1} 7 */ 8 public static <T> Set<Set<T>> getPowerSet(Set<T> originalSet) { 9 Set<Set<T>> sets = new HashSet<Set<T>>(); 10 if (originalSet.isEmpty()) { 11 sets.add(new HashSet<T>()); 12 return sets; 13 } 14 List<T> list = new ArrayList<T>(originalSet); 15 T head = list.get(0); 16 Set<T> rest = new HashSet<T>(list.subList(1, list.size())); 17 for (Set<T> set : getPowerSet(rest)) { 18 Set<T> newSet = new HashSet<T>(); 19 newSet.add(head); 20 newSet.addAll(set); 21 sets.add(newSet); 22 sets.add(set); 23 } 24 return sets; 25 }