求集合的子集在生活中经常遇到,例如集合{1,2,3}子集的个数为23个,分别为{ {},{1}, {2}, {3}, {1,2}, {1,3}, {2,3}, {1,2,3}} 大概有两种思路,一种是二进制方式方法,一种是使用深度遍历思想的方法
二进制表示方法
假设有一个三个元素的集合{1,2,3},集合可用3位二进制表示,如下:
0:000 -> {}
1:001 -> {1}
2:010 -> {2}
3:110 -> {1,2}
4:100 -> {3}
5:101 -> {1,2}
6:011 -> {2,3}
7:111 -> {1,2,3}
代码如下:
public void subSet() { int a[] = {1,2,3,4}; int num = 1 << 4; //子集的个数 int index = 0,k=0; for(int i = 0; i < num; i++) //i 从1到15 就是真子集,i转化成二进制形式 { index = i; k = 0; System.out.print("{"); while(index != 0) { if((index & 1) != 0) { System.out.print(a[k]); } index >>= 1;//二进制每次移位(右移)一位, k++; } System.out.println("}"); } }
算法的输出就是上面的讲解。在实际应用中,常常需要把得到的子集给存储起来,可以把每次得到的子集放入到一个set中,下面将给出案例;
深度优先遍历方法
深度优先遍历方法(DFS)类似于树的先序遍历,它的基本思想是:首先访问图中某一起始点v,然后由v出发访问与v邻接且未被访问的任一顶点v1,再访问与v1邻接且未被访问的任一顶点v2.....,重复上述过程,直至不能再继续向下访问,依次退回到最近访问的顶点,若它还有邻接顶点未被访问过,从这顶点开始,继续上述搜索过程,直到所有顶点被访问过为止。常用在方案问题的求解、排列组合等问题中
public static void dfs(int[] a, int index, ArrayList<Integer> tmp, Set<ArrayList<Integer>> ret) { ret.add(new ArrayList<Integer>(tmp));// 1 需要复制出来一个对象 for (int i = index; i < a.length; i++) { tmp.add(a[i]); dfs(a, i + 1,tmp, ret); //递归过程 tmp.remove(tmp.size() - 1); } }
调用过程
{ int a[] = {1,2,3,4}; Set<ArrayList<Integer>> result = new HashSet<ArrayList<Integer>> (); dfs(a, 0,new ArrayList<Integer>(), result); System.out.println(result); }
具体案例
考虑数字序列{1, 3, 4, 2, 6,7,5,5,8,10,9,10,7,17},任取其中几个数字相加,使得到的和为29,则不同的组合有几种?详见这里
完整代码
package lets.code.every.day; import java.util.*; public class Test { public static int sum(ArrayList<Integer> tmp) { int sum = 0; for (int i : tmp) sum += i; return sum; } public static void dfs(int[] S, int index, ArrayList<Integer> tmp,Set<ArrayList<Integer>> ret) { if (sum(tmp) == 29) //剪枝条件 ret.add(new ArrayList<Integer>(tmp));// 1 需要复制出来一个对象 for (int i = index; i < S.length; i++) { tmp.add(S[i]); dfs(S, i + 1, tmp, ret); tmp.remove(tmp.size() - 1); } } public static void main(String[] args) { int a[] = { 1, 3, 4, 2, 6, 7, 5, 5, 8, 10, 9, 10, 7, 17 }; Set<ArrayList<Integer>> result = new HashSet<ArrayList<Integer>>(); dfs(a, 0, new ArrayList<Integer>(), result); System.out.println(result.size()); } }