前言
“这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战”
- NC27 集合的所有子集(中等)
- 90. 子集 II
集合的所有子集
描述:现在有一个没有重复元素的整数集合S,求S的所有子集
注意:
你给出的子集中的元素必须按升序排列
给出的解集中不能出现重复的元素
输入:
[1,2,3]
返回值:
[[],[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]
思路分析: 回溯主要是3点
- 结束条件
- 当前可以做的选择
- 已经做出的选择
针对这个道题目,要求有序, 因此处理前后都需要进行排序
AC 代码:
ArrayList<ArrayList<Integer>> ans = new ArrayList<>();
public ArrayList<ArrayList<Integer>> subsets(int[] S) {
Arrays.sort(S);
dfs(S, 0, new ArrayList<>());
Collections.sort(ans, new Comparator<ArrayList<Integer>>() {
@Override
public int compare(ArrayList<Integer> o1, ArrayList<Integer> o2) {
if (o1.size() != o2.size()) {
return o1.size() - o2.size();
}
int size = o1.size();
for (int i = 0; i < size; i++) {
if (o1.get(i).equals(o2.get(i))) continue;
return o1.get(i) - o2.get(i);
}
return 0;
}
});
return ans;
}
void dfs(int[] S, int index, ArrayList<Integer> temp) {
ans.add(new ArrayList<>(temp));
for (int i = index; i < S.length; i++) {
temp.add(S[i]);
dfs(S, i + 1, temp);
temp.remove(temp.size() - 1);
}
}
90. 子集 II
描述: 给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
思路分析: 与上面一道题目类似, 只不过给的原始数组中包含重复的元素
- 暴力解法,最后对结果去重
- 回溯 + 剪枝 同一层不可以使用重复的元素
- 若前一个元素和当前元素相同,并且未被访问,则说明前一个元素已经被使用过了。则直接跳过当前元素
- 若前一个元素和当前元素相同,但已被访问,则说明当前元素在前一个元素的分支下,可以使用。
AC 代码:
List<List<Integer>> ans = new ArrayList<>();
boolean[] used;
public List<List<Integer>> subsetsWithDup(int[] nums) {
if (nums == null || nums.length == 0){
return new ArrayList<>();
}
Arrays.sort(nums);
used = new boolean[nums.length];
help(nums, 0, new ArrayList<>());
return ans;
}
private void help(int[] nums, int startIndex, List<Integer> temp){
ans.add(new ArrayList<>(temp));
for (int i = startIndex; i < nums.length; i++){
if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]){
continue;
}
temp.add(nums[i]);
used[i] = true;
help(nums, i + 1, temp);
temp.remove(temp.size() - 1);
used[i] = false;
}
}