2025-03-28 17:37:12 +08:00
|
|
|
|
package backtrack;
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 题目: 90. 子集 II (subsetsWithDup)
|
|
|
|
|
* 描述:给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的 子集(幂集)。
|
|
|
|
|
* 解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
|
|
|
|
|
|
|
|
|
|
示例 1:
|
|
|
|
|
输入:nums = [1,2,2]
|
|
|
|
|
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
|
|
|
|
|
|
|
|
|
|
* 链接:https://leetcode.cn/problems/subsets-ii/
|
|
|
|
|
*/
|
|
|
|
|
//不会,有点难
|
|
|
|
|
public class SubsetsWithDup {
|
2025-07-05 18:04:10 +08:00
|
|
|
|
|
2025-03-28 17:37:12 +08:00
|
|
|
|
public List<List<Integer>> subsetsWithDup(int[] nums) {
|
|
|
|
|
List<List<Integer>> res = new ArrayList<>();
|
|
|
|
|
List<Integer> path = new ArrayList<>();
|
|
|
|
|
// 排序数组,使重复元素相邻,便于剪枝
|
|
|
|
|
Arrays.sort(nums);
|
|
|
|
|
backtrack(res, path, nums, 0);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void backtrack(List<List<Integer>> res, List<Integer> path, int[] nums, int start) {
|
|
|
|
|
// 每次递归都将当前路径加入结果,注意:空集也会被加入
|
|
|
|
|
res.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]);
|
|
|
|
|
backtrack(res, path, nums, i + 1);
|
|
|
|
|
path.remove(path.size() - 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 测试方法
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
SubsetsWithDup solution = new SubsetsWithDup();
|
2025-07-05 18:04:10 +08:00
|
|
|
|
int[] nums = {1, 2, 3};
|
2025-03-28 17:37:12 +08:00
|
|
|
|
List<List<Integer>> subsets = solution.subsetsWithDup(nums);
|
|
|
|
|
System.out.println(subsets);
|
|
|
|
|
// 输出:[[], [1], [1, 2], [1, 2, 2], [2], [2, 2]]
|
|
|
|
|
}
|
|
|
|
|
}
|