Problem:
I:
Given a set of distinct integers, 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,3]
, a solution is:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
II:
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],
[]
]
Analysis:
Solutions:
(I) Recursive method:
void getCombine(vector<vector<int> > &setCombine, vector<int> &combine, vector<int> &S, int startIndex, int num){
if(num==1){
for(int i=startIndex; i<S.size(); ++i){
combine.push_back(S[i]);
setCombine.push_back(combine);
combine.pop_back();
}
}else{
for(int i=startIndex; i<S.size(); ++i){
combine.push_back(S[i]);
getCombine(setCombine, combine, S, i+1, num-1);
combine.pop_back();
}
}
}
vector<vector<int> > subsets(vector<int> &S) {
std::sort(S.begin(), S.end());
vector<vector<int> > colSubset;
vector<int> subset;
colSubset.push_back(subset); //Empty subset.
for(int k=1; k<=S.size(); ++k)
getCombine(colSubset, subset, S, 0, k);
return colSubset;
}
Non-Recursive method:
vector<int> Union(const vector<int>& left, const vector<int>& right)
{
vector<int> r_set;
for(int i = 0; i < left.size(); ++i)
r_set.push_back(left[i]);
for(int i = 0; i < right.size(); ++i)
r_set.push_back(right[i]);
return r_set;
}
vector<vector<int> > subsets(vector<int> &S) {
vector<vector<int> > r_subsets;
vector<int> empty;
r_subsets.push_back(empty);
if(S.empty())
return r_subsets;
sort(S.begin(), S.end());
int max_size = S.size();
vector<vector<vector<int> > > subsets_by_size;
subsets_by_size.resize(max_size);
for(int size = 0; size < max_size; ++size) {
if(size == 0) {
for(int i = 0; i < S.size(); ++i) {
vector<int> subset;
subset.push_back(S[i]);
subsets_by_size[size].push_back(subset);
}
} else {
for(int i = 0; i < subsets_by_size[0].size(); ++i) {
for(int j = 0; j < subsets_by_size[size - 1].size(); ++j) {
if(subsets_by_size[0][i][0] < subsets_by_size[size - 1][j][0])
subsets_by_size[size].push_back(Union(subsets_by_size[0][i], subsets_by_size[size - 1][j]));
}
}
}
}
for(int i = 0; i < max_size; ++i) {
for(int j = 0; j < subsets_by_size[i].size(); ++j)
r_subsets.push_back(subsets_by_size[i][j]);
}
return r_subsets;
}
(
II)
vector<int> Union(const vector<int>& left, const vector<int>& right)
{
vector<int> r_set;
for(int i = 0; i < left.size(); ++i)
r_set.push_back(left[i]);
for(int i = 0; i < right.size(); ++i)
r_set.push_back(right[i]);
return r_set;
}
vector<vector<int> > subsetsWithDup(vector<int> &S) {
vector<vector<int> > r_subsets;
vector<int> empty;
r_subsets.push_back(empty);
if(S.empty())
return r_subsets;
sort(S.begin(), S.end());
int max_size = S.size();
vector<vector<vector<int> > > subsets_by_size;
subsets_by_size.resize(max_size);
for(int size = 0; size < max_size; ++size) {
if(size == 0) {
for(int i = 0; i < max_size;) {
vector<int> subset;
if(i == max_size - 1 || S[i] < S[i + 1]) {
subset.push_back(S[i]);
subsets_by_size[size].push_back(subset);
++i;
} else {
int sum_same = 0;
for(int j = i; j < max_size; ++j) {
if(S[i] == S[j]) ++sum_same;
else break;
}
for(int j = 0; j < sum_same; ++j) {
subset.push_back(S[i]);
subsets_by_size[size].push_back(subset);
}
i += sum_same;
}
}
} else {
for(int i = 0; i < subsets_by_size[0].size(); ++i) {
for(int j = 0; j < subsets_by_size[size - 1].size(); ++j) {
if(subsets_by_size[0][i][0] < subsets_by_size[size - 1][j][0])
subsets_by_size[size].push_back(Union(subsets_by_size[0][i], subsets_by_size[size - 1][j]));
}
}
}
}
for(int i = 0; i < max_size; ++i) {
for(int j = 0; j < subsets_by_size[i].size(); ++j)
r_subsets.push_back(subsets_by_size[i][j]);
}
return r_subsets;
}
Java
:
Python: