1、问题描述
Given a collection of integers that might contain duplicates, nums, return all possible subsets.
Note: The solution set must not contain duplicate subsets.
For example,
If nums = [1,2,2]
, a solution is:
[ [2], [1], [1,2,2], [2,2], [1,2], [] ]
2、边界条件:重复数字
3、思路:组合问题,用递归,但是有重复数字,需要去重,排序后更利于去重。对于一个数字,有两种选择:选或者不选,然后进入下一层递归。
4、代码实现
方法一:
class Solution { public List<List<Integer>> subsetsWithDup(int[] nums) { List<List<Integer>> results = new ArrayList<>(); Arrays.sort(nums); subsetWithDup(results, new ArrayList<Integer>(), nums, 0); return results; } public void subsetWithDup(List<List<Integer>> results, List<Integer> cur, int[] nums, int index) { if (index == nums.length) {//base case index == nums.length ArrayList<Integer> result = new ArrayList<>(cur); if (!results.contains(result)) { //去重,这种去重的方法不能提高效率,只是事后的手段。 results.add(new ArrayList<Integer>(cur)); } return; } subsetWithDup(results, cur, nums, index + 1); cur.add(nums[index]); subsetWithDup(results, cur, nums, index + 1); cur.remove(cur.size() - 1); } }
方法二:
class Solution { public List<List<Integer>> subsetsWithDup(int[] nums) { List<List<Integer>> results = new ArrayList<>(); Arrays.sort(nums); subsetWithDup(results, new ArrayList<Integer>(), nums, 0); return results; } public void subsetWithDup(List<List<Integer>> results, List<Integer> cur, int[] nums, int index) { if (index == nums.length) {//base case index == nums.length results.add(new ArrayList<Integer>(cur)); return; } for (int i = index; i < nums.length; i++) { if (i != index && nums[i] == nums[i - 1]) {//去重,这种去重是事前去重,能提高效率。 continue; } cur.add(nums[i]); subsetWithDup(results, cur, nums, i + 1);//组合问题这里从i+1开始,排列才从index+1开始 cur.remove(cur.size() - 1); } subsetWithDup(results, cur, nums, nums.length);//不要忘记 空集合;也可在前面条件,即
/*
for (int i = index; i <= nums.length; i++) {
if (i == nums.length) {
subsetWithDup(results, cur, nums, i);
return;
}
}
*/
} }
5、时间复杂度: 空间复杂度:
6、用到的api:boolean reaults.contains(ArrayList<Integer>) List<Lsit<Integer>> results