Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set).
Note: The solution set must not contain duplicate subsets.
Example:
Input: [1,2,2]
Output:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/subsets-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
方法一:
遍历每个数字,都尝试加入,用list.contains判断是否重复,代码代码简单,不赘述。
方法二:
为了避免有重复的元素,如果碰到的元素和上一个不一样,我们只在上一个元素的处理结果之后,追加元素,以{1,2,2,3}为例如下:
先对数组进行排序。
① []
②nums第一个数字1,则集合为{[],[1]}
③nums第二个数字2,与上个数字不一样,就往集合中所有的元素都追加2,放入最终集合中,则集合为{[],[1],[2],[1,2]},保存这次开始放入的元素位置为元素[2]的位置。
④nums第三个数字2,和上个数字一样,那么,就从上个元素开始放入的元素开始,之后追加。即只往集合中元素[2]和[1,2]后追加,那么集合最终为{[],[1],[2],[1,2],[2,2],[1,2,2]},保存这次开始放入的元素位置为元素[2,2]的位置。
⑤nums第四个数字3,和上数字不一样,那么久就头开始添加,最终结果是{[],[1],[2],[1,2],[2,2],[1,2,2],[3],[1,3],[2,3],[1,2,3],[2,2,3],[1,2,2,3]}
这样,我们只需要用一个数字记录,上次追加的位置即可。代码如下:
class Solution {
List<List<Integer>> ans = new ArrayList<>();
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums);
ans.add(new ArrayList<Integer>());
if (nums.length == 0)
return ans;
int lastNum = nums[0] - 1;
int lastPutIndex = 0;
for (int index = 0; index < nums.length; index++) {
// 如果这个数字与上个相同,则从上次记录增加的位置开始
if (nums[index] == lastNum) {
int tmpSize = ans.size();
for (int i = lastPutIndex; i < tmpSize; i++) {
List<Integer> list = new ArrayList<>(ans.get(i));
list.add(nums[index]);
ans.add(list);
}
lastPutIndex = tmpSize;
} else {
//不相同,则从整个集合遍历,当前集合的每个元素都加入这个数字
int tmpSize = ans.size();
for (int i = 0; i < tmpSize; i++) {
List<Integer> list = new ArrayList<>(ans.get(i));
list.add(nums[index]);
ans.add(list);
}
lastNum = nums[index];
lastPutIndex = tmpSize;
}
}
return ans;
}
}
本文介绍了一种解决含有重复元素的数组生成所有可能子集(幂集)的算法。通过排序和记录上次追加元素的位置,避免了重复子集的产生。以[1,2,2,3]为例,详细解释了算法的实现过程。
1168

被折叠的 条评论
为什么被折叠?



