题解 | #集合的所有子集(二)#
集合的所有子集(二)
https://www.nowcoder.com/practice/a3dfd4bc8ae74fad9bc65d5ced7ae813
import java.util.*;
public class Solution {
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
int n;
ArrayList<Integer> path = new ArrayList<>();
boolean[] used = new boolean[n];
public ArrayList<ArrayList<Integer>> subsets (int[] nums) {
Arrays.sort(nums);
n = nums.length;
for (int i = 0; i <= n; i++) {
dfs(0, i, nums);
}
res.sort(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
ArrayList<Integer> o11 = (ArrayList<Integer>) o1;
ArrayList<Integer> o12 = (ArrayList<Integer>) o2;
int i = 0;
int j = 0;
while (i < o11.size() || j < o12.size()) {
int x = Integer.MIN_VALUE;
int y = Integer.MIN_VALUE;
if (i == o11.size()) {
y = o12.get(j);
i++;
} else if (j == o12.size()) {
x = o11.get(i);
j++;
} else {
x = o11.get(i);
y = o12.get(j);
i++;
j++;
}
if (x > y) return 1;
if (x < y) return -1;
}
return 0;
}
});
return res;
}
void dfs(int start, int k, int[] nums) {
if (k == 0) {
res.add(new ArrayList<>(path));
return;
}
for (int i = start; i < n; i++) {
if (i > start && nums[i - 1] == nums[i]) continue;
path.add(nums[i]);
dfs(i + 1, k - 1, nums);
path.remove(path.size() - 1);
}
}
}
我用的是经典模板,更好理解,这里稍微麻烦的是需要传入一个comparator比较器,因为牛客需要按字典序输出。
题的执行过程:
我需要获得长度为0到n的子集序列,先从0开始,如果此时所需寻找的子集长度为0,添加到结果集,
然后寻找长度为1的子集序列,start下标在每次寻找时都要加一,保证子集不会回头去找。
去重的话,使用i>start和nums[i] == nums[i-1] continue 来保证不会有重复的。
举个例子: 1 2 2
先找子集个数为0的,此时需要的子集个数为0,return。
再找子集个数为1的,传入start=0, k = 1, 表示从第一个开始取数,此时需要的子集个数为1,找到之后,加入path,k-1;
此时k=0,将它加入到结果集。
循环,从 下标一开始,如果与前一个相同,则会重复,所以continue,接着刚才的操作。
理解起来很难,加油。

