原题:
即返回给定数组的所有子集。
思考过程&解题思路:
一开始想到用递归的办法(其实是深度优先遍历DFS);后来看到更高明的办法:位操作。其实一个集合子集数量就是2的(集合元素个数)次方。因为对于任何一个元素,在某个子集中要么有,要么没有。所以子集个数就是这个情况数。用二进制数字表示当前子集是否有数组某个元素。二进制数字中第n位为1表示当前子集有数组的第n个元素。
结果代码:
List<List<Integer>> ret = new ArrayList<>();
public List<List<Integer>> subsetsDFS(int[] nums) {
ret.add(new ArrayList<>());//先加上空集
for (int i = 0;i < nums.length;i++){
List<Integer> integers = new ArrayList<>();
DFS(integers,i,nums);
}
return ret;
}
public void DFS(List<Integer> former,int begin,int nums[]){
List<Integer> subRet = new ArrayList<>();
subRet.addAll(former);
subRet.add(nums[begin]);//把上次传来的结果集和第二个参数对应数组的元素传入新的结果子集中
ret.add(subRet);//新的结果子集添加到结果集
while (begin < nums.length - 1) DFS(subRet,++begin,nums);//关键在于这里,只往后递归,避免重复,逐个添加后面的元素,继续递归
}
public List<List<Integer>> subsets(int[] nums) {
int len = nums.length;
for (int i = 0;i < 1 << len;i++){//i的二进制数字中,第n位为0表示当前结果子集中没有数组第n个元素。为1表示有这个元素
List<Integer> subRet = new ArrayList<>();
for (int j = 0;j < len;j++){//j表示数组第j个元素
if ((i & (1 << j)) != 0)//1向左移动j位后,和i作&运算,如果为0,说明i的第j位为0,否则为1
subRet.add(nums[j]);
}
ret.add(subRet);
}
return ret;
}