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],
[]
]
Solution. Let’s first talk about the normal Subset problem, which doesn’t has duplicate. There is a loop way rather than recursion. Let’s say [1, 2, 3]. Assume we already have subset(1, 2), which is {[], [1], [2], [1, 2]}.
For 3, we can either add it {[], [1], [2], [1, 2]}
or not add it {[3], [1, 3], [2, 3], [1, 2, 3]}.
So we will have subset(1, 2, 3), which is {[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]}. It’s like for each element, we can either pick up or not pick up it.
For Subsets II problem, let’s say we want to get subset for [1, 2, 3, 3]. Assume we have subset(1, 2) = {[], [1], [2], [1, 2]}. Based on subset(1, 2), we can either add zero 3, add one 3, or two 3 in the subset(1, 2). So the process is like:

public static List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> ans = new ArrayList<>(Collections.singleton(new ArrayList<>()));
Arrays.sort(nums);
int i = 0;
while (i < nums.length) {
int next = i + 1;
while (next < nums.length && nums[next] == nums[i]) {
next++;
}
int size = ans.size();
for (int j = 0; j < size; j++) {
List<Integer> curr = new ArrayList<>(ans.get(j));
for (int k = 1; k <= next - i; k++) {
curr.add(nums[i]);
ans.add(new ArrayList<>(curr));
}
}
i = next;
}
return ans;
}
Check my code on github.