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], [] ]
解題思路:與78題不同,本題可能存在相同的元素,如何刪除相同的集合則是本題的難點。
以[1,2,2]爲例,以78解題思路(回溯剪枝),得到子集的順序爲[[],[1],[1,2],[1,2,2],[1,2],[2],[2,2],[2]],相當於先找到第一個元素構成的所有子集,再找第二個元素構成的子集,由此類推,如果繼續採用這種思路,在剔除的時候會有點麻煩。
本題用另外一種思路,與78題中的非遞歸解法一致,從最終結果來看,求得子集順序爲[[],[1],[2],[1,2],[2],[1,2],[2,2],[1,2,2]],即先求元素個數爲0的子集,接着求個數爲1的子集,由此類推,具體做法如下:
先將nums排序,來保證所有相同的元素在一起,設一個ans數組記錄已經有的子集,將空集壓入。
壓入1:調出空集,將1壓入得到[[],[1]]
壓入2:首先調出[],得到[2],再調出[1],得到[1,2],當前結果爲[[],[1],[2],[1,2]]。
壓入第二個2:從第二次得出的子集,依次再在每個子集中壓入2,最終得到[[],[1],[2],[1,2],[2],[1,2],[2,2],[1,2,2]]
此即爲78題非遞歸的解法,如果要用於本題,在壓入第二個2的時候,需要去除[[],[1],[2],[1,2]]中不含有第一個2的子集,在剩下的子集中壓入第二個2。換言之,需要修改left。
當此時num的值與上一次遍歷的值一致,left應該爲壓入上一個num值前的子集個數。
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>>ans;
vector<int>tempans;
ans.push_back(tempans);
int right = 1, left = 0, len = 0;
for(int i = 0; i < nums.size(); ++ i){
if(i != 0 && (nums[i] == nums[i-1]))
left = ans.size() - len;
else
left = 0;
right = ans.size();
len = right - left;
for(int j = left; j < right; ++ j){
tempans = ans[j];
tempans.push_back(nums[i]);
ans.push_back(tempans);
}
}
return ans;
}
};