题目链接
78. 子集
题目描述
解题思路
1.回溯法
类似题目还有:
39. 组合总和
40. 组合总和 II
41. 全排列
42. 全排列 II
43. 子集
44. 子集 II
这类题目都是同一类型的,用回溯算法!
其实回溯算法关键在于:不合适就退回上一步
然后通过约束条件, 减少时间复杂度.
2.迭代法
逐个枚举,空集的幂集只有空集,每增加一个元素,让之前幂集中的每个集合,追加这个元素,就是新增的子集。
AC代码
1.回溯法
class Solution {
List<List<Integer>> ans = new LinkedList<>();
List<Integer> temp = new LinkedList<>();
void dfs(int[] nums, int level, int[] vis,int start){
ans.add(new LinkedList(temp));
if(level == nums.length) return;
//本题是打印所有子集,我不是全排列,所以dfs递归需要回溯:
//dfs递归中每次for循环都是从i=0开始,则表示全排列
//dfs递归中每次for循环都是从i=start开始,表示子集(i=start,然后传入i,这已经进行剪枝了!)
for(int i = start; i < nums.length; i++){
if(vis[i] == 0){
vis[i] = 1;
temp.add(nums[i]);
dfs(nums,level+1,vis,i);
temp.remove(temp.size()-1);
vis[i] = 0;
}
}
}
public List<List<Integer>> subsets(int[] nums) {
if(nums.length == 0) return ans;
int[] vis = new int[nums.length];
dfs(nums,0,vis,0);
return ans;
}
}
2.迭代法
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
res.add(new ArrayList<Integer>());
for (Integer n : nums) {
int size = res.size();
for (int i = 0; i < size; i++) {
List<Integer> newSub = new ArrayList<Integer>(res.get(i));
newSub.add(n);
res.add(newSub);
}
}
return res;
}
}