Given a collection of integers that might contain duplicates, nums, return all possible subsets.
Note:
- Elements in a subset must be in non-descending order.
- The solution set must not contain duplicate subsets.
For example,
If nums = [1,2,2]
, a solution is:
[ [2], [1], [1,2,2], [2,2], [1,2], [] ]
这一题是subset的变形,不同的是加入了重复项,这样的话,就引入了去重的问题。同样采用回溯的方法,这里所有已知子集项都有两种操作的可能,一个是保持当前项不变,而是添加新元素构成新的子集。那么如何把去重考虑在这两个步骤中呢,分析可以知道,当元素是重复元素的时候,子集项的操作就只能有一种了,不能保持当前项不变了,必须添加新元素;因为其他的自己项可以构造出这个重复的子集项,所以该子集项必须添加一个元素,这样才能保持唯一性,这也是这道题目的关键点,想明白这个之后,只在之前的subset的基础上稍作修改,就可以解决这个问题了。
class Solution {
public:
//回溯法,与没有重复项求字串不一样的是,如何处理重复项
//巧妙的在出现重复项时,重复项不能保留本身,只能添加重复的元素
//不包含重复项的,还是有两种操作,添加新元素或者不变
vector<vector<int> > Res;
void buildSubSet(vector<int> &nums, int CurIndex, vector<int> tmpVec)
{
if(CurIndex == (nums.size() - 1))
{
if(tmpVec.empty() || tmpVec[tmpVec.size() - 1] != nums[CurIndex])
{
Res.push_back(tmpVec);
}
tmpVec.push_back(nums[CurIndex]);
Res.push_back(tmpVec);
return;
}
if(tmpVec.empty() || tmpVec[tmpVec.size() - 1] != nums[CurIndex])
{
buildSubSet(nums, CurIndex + 1, tmpVec);
}
tmpVec.push_back(nums[CurIndex]);
buildSubSet(nums, CurIndex + 1, tmpVec);
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<int> tmpVec;
buildSubSet(nums, 0, tmpVec);
return Res;
}
};