子集
难度:中等
题目描述
给你一个整数数组 nums
,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
示例1
输入: nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
示例2
输入: nums = [0]
输出:[[],[0]]
题解
先将数组排序,生成所有的子集,排序之后相同的元素位于相邻的位置,利用这一特点去重
去重操作主要是判断前一个数和当前数字是否相等,如果不相等就继续进行之后的操作,相等则跳出本次回溯
当遍历到数组中下标为i
的数时,执行如下操作:
- 如果 i = n i = n i=n,那么得到一个子集,将子集添加到答案中
- 如果
i
<
n
i < n
i<n,则分别考虑将其加入到子集和不加入到子集中两种情况
- 不将其加入子集则继续对 i + 1 i + 1 i+1 进行回溯
- 如果可以加入到子集中,则将其加入到子集中之后继续回溯,回溯之后将当前子集的末尾元素移除,恢复到初始状态
遍历结束之后,就可以得到最终答案
想法代码
public class Solution
{
public static void Main(String[] args)
{
int[] nums = { 1, 2, 2 };
Solution solution = new Solution();
IList<IList<int>> ans = new List<IList<int>>();
ans = solution.SubsetsWithDup(nums);
foreach (var i in ans)
{
foreach (var j in i)
{
Console.Write(j + " ");
}
Console.WriteLine();
}
}
IList<IList<int>> powerSet = new List<IList<int>>();
IList<int> temp = new List<int>();
int[] nums;
int n;
public IList<IList<int>> SubsetsWithDup(int[] nums)
{
Array.Sort(nums);
this.nums = nums;
this.n = nums.Length;
Backtrack(0, false);
return powerSet;
}
public void Backtrack(int index, bool prevSelected)
{
if (index == n)
{
powerSet.Add(new List<int>(temp));
}
else
{
Backtrack(index + 1, false);
if (index == 0 || nums[index - 1] != nums[index] || prevSelected)
{
temp.Add(nums[index]);
Backtrack(index + 1, true);
temp.RemoveAt(temp.Count - 1);
}
}
}
}