题目链接:
https://www.lintcode.com/problem/subsets-ii/description
给定一个可能具有重复数字的列表,返回其所有可能的子集。
Example
样例 1:
输入:[0]
输出:
[
[],
[0]
]
样例 2:
输入:[1,2,2]
输出:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
Challenge
你可以同时用递归与非递归的方式解决么?
Notice
- 子集中的每个元素都是非降序的
- 两个子集间的顺序是无关紧要的
- 解集中不能包含重复子集
思路:跟17题子集相类似。
在遍历数组时,判断当前元素是否出现过,没出现过,解法如17题。
若当前元素出现过,如{1,2,2,2},
遍历完第0、1个元素后,结果子集res为{{},{1},{2},{1,2}},
遍历第2个元素时发现,当前元素与第1个元素相等,则将当前加入{2}和{1,2}中变成{2,2}和{1,2,2},加入res,
res变成{{},{1},{2},{1,2},{2,2},{1,2,2}}
遍历第3个元素,遍历res时初始下标变了,res变成{{},{1},{2},{1,2},{2,2},{1,2,2},{2,2,2},{1,2,2,2}}
代码如下:
public class Solution {
/**
* @param nums: A set of numbers.
* @return: A list of lists. All valid subsets.
*/
public List<List<Integer>> subsetsWithDup(int[] nums) {
// write your code here
List<List<Integer>> res = new ArrayList<>();
res.add(new ArrayList<>());
Arrays.sort(nums);
int dup = 1;
for(int i=0; i<nums.length; i++) {
if(i-1>=0 &&nums[i]==nums[i-1]) {
dup ++;
}else{
dup = 1;
}
int resSize = res.size();
int startIndex = 0;
if(dup>1) {
startIndex = resSize/dup*(dup-1);
}
for(int j=startIndex; j<resSize; j++) {
List<Integer> list = new ArrayList<>(res.get(j));
list.add(nums[i]);
res.add(list);
}
}
return res;
}
}