一、题目
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
示例 1:
输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
提示:
- 1 <= nums.length <= 10
- -10 <= nums[i] <= 10
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/subsets-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、分析及代码
1. 回溯法
(1)思路
结合回溯法求所有子集,对于连续的 range 个重复元素,在指针后移 range 位的同时依次选取 0 - range 个数字,避免子集重复。
(2)代码
class Solution {
List<List<Integer>> ans;//解集
public List<List<Integer>> subsetsWithDup(int[] nums) {
ans = new ArrayList<List<Integer>>();
Arrays.sort(nums);//排序,使重复元素相邻
List<Integer> list = new ArrayList<Integer>();
subSet(nums, list, 0);
return ans;
}
//回溯法求所有子集
public void subSet(int[] nums, List<Integer> list, int i) {
if (i == nums.length) {
//遍历完nums,将当前数列加入解集
ans.add(new ArrayList<Integer>(list));
return;
}
int range = 1;//计算重复元素范围
while (i + range < nums.length && nums[i + range] == nums[i])
range++;
//在当前重复元素中,依次取0-range个元素
subSet(nums, list, i + range);
for (int j = 0; j < range; j++) {
list.add(nums[i]);
subSet(nums, list, i + range);
}
for (int j = 0; j < range; j++)//恢复数列
list.remove(list.size() - 1);
return;
}
}
(3)结果
执行用时 :1 ms,在所有 Java 提交中击败了 100.00% 的用户;
内存消耗 :38.6 MB,在所有 Java 提交中击败了 76.22% 的用户。
三、其他
暂无。