public class Num78子集 {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
//3个数有8种组合,即0-2^3-1,,判断每一个二进位是不是1就选中哪一个数字
for (int i = 0; i < 1 << nums.length; i++) {
List<Integer> path = new ArrayList<>();
for (int j = 0; j < nums.length; j++) {
//判断i的第j为是不是1
if ((i >> j & 1) == 1) {
path.add(nums[j]);
}
}
ans.add(path);
}
return ans;
}
}
class Solution {
// assume no concurrency
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
if (nums.length == 0) {
return res;
}
// 遍历每个位置放什么元素
dfs(nums, 0, new ArrayList<Integer>());
return res;
}
private void dfs(int[] nums, int start, ArrayList<Integer> path) {
// 和permutation,combination不一样, 每个中间节点都是答案,都需要存储,所以不能dfs到最下面一层才计算答案
res.add(new ArrayList<>(path));
// 尝试每个数字加入当前位子, 有点像combination,取数不能从i=0开始,应该从i=start(上个数字位置的下一个位置)开始选取,才不会重复,比如,选取了1,2,那么之后不能选取2,1
for (int i = start; i < nums.length; i++) {
path.add(nums[i]);
dfs(nums, i + 1, path);
path.remove(path.size() - 1);
}
}
}
class Solution {
List<List<Integer>> ans = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums);
dfs(nums, 0);
return ans;
}
private void dfs(int[] nums, int start) {
ans.add(new ArrayList<>(path));
for (int i = start; i < nums.length; i++) {
//如果当前元素和起始元素重复则跳过
if(i>start&&nums[i]==nums[i-1]) continue;
path.add(nums[i]);
dfs(nums, i + 1);
path.remove(path.size() - 1);
}
}
}