題目
Given a collection of integers that might contain duplicates, nums, return all possible subsets.
Note: 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],
[]
]
解題之法
// Recursion
class Solution {
public:
vector<vector<int> > subsetsWithDup(vector<int> &S) {
vector<vector<int> > res;
vector<int> out;
sort(S.begin(), S.end());
getSubsets(S, 0, out, res);
return res;
}
void getSubsets(vector<int> &S, int pos, vector<int> &out, vector<vector<int> > &res) {
res.push_back(out);
for (int i = pos; i < S.size(); ++i) {
out.push_back(S[i]);
getSubsets(S, i + 1, out, res);
out.pop_back();
while (S[i] == S[i + 1]) ++i;
}
}
};
分析
對于遞歸的解法,根據之前 Subsets 子集合 里的構建樹的方法,在處理到第二個2時,由于前面已經處理了一次2,這次我們只在添加過2的[2] 和 [1 2]后面添加2,其他的都不添加,那么這樣構成的二叉樹如下圖所示:
[]
/ \
/ \
/
[1] []
/ \ /
/ \ / \
[1 2] [1] [2] []
/ \ / \ / \ /
[1 2 2] [1 2] X [1] [2 2] [2] X []
代碼只需在原有的基礎上增加一句話,while (S[i] == S[i + 1]) ++i; 這句話的作用是跳過樹中為X的葉節點,因為它們是重復的子集,應被拋棄。
整個添加的順序為:
[]
[1]
[1 2]
[1 2 2]
[2]
[2 2]