方法1: 这道题目是78题的变种,变成了input可能含有duplicate。理论上来说78题的所有解法最后加一步筛查duplicate的步骤都可以。所以这边方法1,我采用的是78题的解法3,加上一个hashset。
class Solution {
public List<List<Integer>> subsetsWithDup(int[] nums) {
Set<List<Integer>> set = new HashSet<>();
int n = nums.length;
for (int i = (int)Math.pow(2, n); i < (int)Math.pow(2, n + 1); ++i) {
// generate bitmask, from 0..00 to 1..11
String bitmask = Integer.toBinaryString(i).substring(1);
// append subset corresponding to that bitmask
List<Integer> curr = new ArrayList();
for (int j = 0; j < n; ++j) {
if (bitmask.charAt(j) == '1') curr.add(nums[j]);
}
Collections.sort(curr);
set.add(curr);
}
return new ArrayList<>(set);
}
}
方法2: base on 78题方法1。我们keep一个prev来保存上一次新增的subsets,如果这层和上层是相同数字,则这一轮我们只把当前数字加进prev中;否则我们把当前数字加到已有的output中。建议自己走一遍程序就会明白。
class Solution {
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> output = new ArrayList();
output.add(new ArrayList<Integer>());
List<List<Integer>> prev = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
int num = nums[i];
List<List<Integer>> newSubsets = new ArrayList();
if(i != 0 && num == nums[i - 1]){
for(List<Integer> curr : prev){
newSubsets.add(new ArrayList<Integer>(curr){{add(num);}});
}
}else{
for (List<Integer> curr : output) {
newSubsets.add(new ArrayList<Integer>(curr){{add(num);}});
}
}
for (List<Integer> curr : newSubsets) {
output.add(curr);
}
prev = newSubsets;
}
return output;
}
}
总结:
- 这道题目还有一种解决方案,这边我附上链接。复盘的时候记得自己过一遍这个方法。