题目描述:
解题思路:
可以使用遍历的方式,每次遇到新的元素,循环加入到已经有的集合中。
参考代码:
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> res = new ArrayList<>(1 << nums.length);
//先添加一个空的集合
res.add(new ArrayList<>());
for (int num : nums) {
//每遍历一个元素就在之前子集中的每个集合追加这个元素,让他变成新的子集
for (int i = 0, j = res.size(); i < j; i++) {
//遍历之前的子集,重新封装成一个新的子集
List<Integer> list = new ArrayList<>(res.get(i));
//然后在新的子集后面追加这个元素
list.add(num);
//把这个新的子集添加到集合中
res.add(list);
}
}
return res;
}
第二种方法是回溯,回溯模板一套就可以了。
参考代码:
public static List<List<Integer>> subsets3(int[] nums) {
List<List<Integer>> lists=new ArrayList<>();
List<Integer> temp=new ArrayList<>();
dfs(lists,temp,nums,0);
return lists;
}
private static void dfs(List<List<Integer>> lists, List<Integer> temp, int[] nums, int i) {
lists.add(new ArrayList<>(temp));
for (int j = i; j < nums.length; j++) {
temp.add(nums[j]);
dfs(lists,temp,nums,j+1);
temp.remove(temp.size()-1);
}
}
第三种方法很巧妙,是利用位运算,通过找规律发现0—2^n-1对应的二进制的01值可以来代表那个元素不取,那个元素要抓取,利用这个规律可以做出来这道题。
参考代码:
public static List<List<Integer>> subsets4(int[] nums) {
List<List<Integer>> res=new ArrayList<>();
for (int i = 0; i < (1<<nums.length); i++) {
List<Integer> templist=new ArrayList<>();
for (int j = 0; j < nums.length; j++) {
if(((i>>j)&1)==1) templist.add(nums[nums.length-j-1]);
}
res.add(templist);
}
return res;
}