Given a collection of integers that might contain duplicates, S, 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 S = [1,2,2]
, a solution is:
[ [2], [1], [1,2,2], [2,2], [1,2], [] ]
My solution: DFS, set(judge if there is a repetition)
class Solution {
public:
vector<vector<int> > subsetsWithDup(vector<int> &S) {
if (S.empty()) return ans;
sort(S.begin(), S.end());
length = S.size();
s = S;
DFS(0);
for (set<vector<int> >::iterator iter = preAns.begin(); iter != preAns.end(); iter++) ans.push_back(*iter);
return ans;
}
void DFS(int pos) {
if (pos == length) {
preAns.insert(aAns);
return;
}
DFS(pos + 1);
aAns.push_back(s[pos]);
DFS(pos + 1);
aAns.pop_back();
}
int length;
set<vector<int> > preAns;
vector<vector<int> > ans;
vector<int> aAns;
vector<int> s;
};
This solution below is excellent:
class Solution {
public:
vector<vector<int> > subsetsWithDup(vector<int> &S) {
sort(S.begin(), S.end());
vector<vector<int> > result(1);
int oldval=S[0];
int oldj=0;
for(int i=0; i<S.size(); i++){
int temp=oldj;
if(S[i]!=oldval){
oldval=S[i]; temp=0;
}
int j=result.size();
oldj=j;
while(j-->temp){
//note temp here help avoid creating duplicate subsets
result.push_back(result[j]);
result.back().push_back(S[i]);
}
}
return result;
}
};
the explanation of the parameters:
oldval: to store the last value in S(S[i - 1]), for comparing with S[i] to determine whether there is a repetition;
oldj: the last size of result;
temp: the ending point of the process which is for creating new subset;
Now let's observe what happens when this solution is working:
Notice that vector<vector<int> > result(1) set the result size as 1, result[0] = {}, a empty set.
If S[i] != oldval(means it is not a repetition):
temp = 0, which means the making new subsets job will traverse the result before. for example, if the result before is {{}, {1}} and S[i] = 2,
now the new subsets are creating by add S[i] to the end of every subset before:{{}, {1}, {2}, {1, 2}}
If S[i] == oldval:
temp = oldj, now the creating job will start from the result size and end at the old result size. for example, if the result before is {{}, {1}, {2}, {1, 2}} and S[i] = 2, oldj = 2(from above). Now the creating job will traverse {2} and {1, 2}, the result is :
{{}, {1}, {2}, {1, 2}, {1, 2, 2}, {2, 2}}, which is the answer for the example in the problem.