题目描述(传送门)
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
回溯法
回溯法又称为试探法,但当探索到某一步时,发现原先选择达不到目标,就退回一步重新选择,这种走不通就退回再走的算法就叫做回溯法。
方法一:回溯
算法思路
class Solution {
public static List<List<Integer>> subsets(int[] nums) {
List<Integer> list = new ArrayList<>();
List<List<Integer>> listList = new ArrayList<>();
listList.add(list);// 添加【】进去
subsetsHelper(0, nums, list, listList);
return listList;
}
private static void subsetsHelper(int i, int[] nums, List<Integer> list, List<List<Integer>> listList) {
if (i >= nums.length) {
return;
}
list.add(nums[i]);
listList.add(new ArrayList<>(list));//在这里注意需要new一下
subsetsHelper(i + 1, nums, list, listList);
list.remove(list.size() - 1);
subsetsHelper(i + 1, nums, list, listList);
}
}
方法二:位运算
预备知识
算法思路
若一个集合有三个元素ABC,则三个元素有2^3 = 8种组成集合的方式,用0-7表示这些集合,
这个里边有点小问题,&之后0就是0,1是不为0的数。
public static List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> listList = new ArrayList<>();
int all_set = 1 << nums.length;
for (int i = 0; i < all_set; i++) {
List<Integer> list = new ArrayList<>();
for (int j = 0; j < nums.length; j++) {
//System.out.println(i & (1 << j));
if ((i & (1 << j)) != 0) {
list.add(nums[j]);
}
}
listList.add(list);
}
return listList;
}
不同的结果顺序可以体会两种算法的区别。