leetcode:暴力枚举法之Subsets 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],
[]
]
这题有重复元素,与Subsets类似(没有重复,相当于每个元素只能选0 或1 次),这里扩充到了每个元素可以选0 到若干次而已。
c++实现;
法一:递归
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void dfs(const vector<int> &S, vector<int>::iterator start,vector<int> &path, vector<vector<int> > &result) ;
void dfs(const vector<int> &S, vector<int> &count,vector<int> &selected, size_t step, vector<vector<int> > &result);
//递归;增量构造法
//vector<vector<int> > subsetsWithDup(vector<int> &S)
//{
// sort(S.begin(), S.end()); // 必须排序
// vector<vector<int> > result;
// vector<int> path;
// dfs(S, S.begin(), path, result);
// return result;
//}
//void dfs(const vector<int> &S, vector<int>::iterator start,vector<int> &path, vector<vector<int> > &result)
//{
// result.push_back(path);
// for (auto i = start; i < S.end(); i++)
// {
// if (i != start && *i == *(i-1))
// continue;
// path.push_back(*i);
// dfs(S, i + 1, path, result);
// path.pop_back();
// }
//}
//递归;位向量法
vector<vector<int> > subsetsWithDup(vector<int> &S)
{
vector<vector<int> > result; // 必须排序
sort(S.begin(), S.end());
vector<int> count(S.back() - S.front() + 1, 0);
// 计算所有元素的个数
for (auto i : S)
{
count[i - S[0]]++;
}
// 每个元素选择了多少个
vector<int> selected(S.back() - S.front() + 1, -1);
dfs(S, count, selected, 0, result);
return result;
}
void dfs(const vector<int> &S, vector<int> &count,vector<int> &selected, size_t step, vector<vector<int> > &result)
{
if (step == count.size())
{
vector<int> subset;
for(size_t i = 0; i < selected.size(); i++)
{
for (int j = 0; j < selected[i]; j++)
{
subset.push_back(i+S[0]);
}
}
result.push_back(subset);
return;
}
for (int i = 0; i <= count[step]; i++)
{
selected[step] = i;
dfs(S, count, selected, step + 1, result);
}
}
int main()
{
int a[3]={1,2,2};
vector<int>vec(a,a+3);
vector<vector<int>> out;
out= subsetsWithDup(vec);
vector<vector<int>>::iterator pp;
vector<int>::iterator it;
for(pp=out.begin();pp<out.end();pp++)
{
for (it=(*pp).begin();it<(*pp).end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
return 0;
}
测试结果:
法二:迭代
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <iterator>
using namespace std;
//迭代;增量构造法
//vector<vector<int> > subsetsWithDup(vector<int> &S)
//{
// sort(S.begin(), S.end()); // 必须排序
// vector<vector<int> > result(1);
// size_t previous_size = 0;
// for (size_t i = 0; i < S.size(); ++i)
// {
// const size_t size = result.size();
// for (size_t j = 0; j < size; ++j)
// {
// if (i == 0 || S[i] != S[i-1] || j >= previous_size)
// {
// result.push_back(result[j]);
// result.back().push_back(S[i]);
// }
// }
// previous_size = size;
// }
// return result;
//}
//迭代;二进制法
vector<vector<int> > subsetsWithDup(vector<int> &S)
{
sort(S.begin(), S.end()); // 必须排序
// 用set 去重,不能用unordered_set,因为输出要求有序
set<vector<int> > result;
const size_t n = S.size();
vector<int> v;
for (size_t i = 0; i < 1U << n; ++i)
{
for (size_t j = 0; j < n; ++j)
{
if (i & 1 << j)
v.push_back(S[j]);
}
result.insert(v);
v.clear();
}
vector<vector<int> > real_result;
copy(result.begin(), result.end(), back_inserter(real_result));
return real_result;
}
int main()
{
int a[3]={1,2,2};
vector<int>vec(a,a+3);
vector<vector<int>> out;
out= subsetsWithDup(vec);
vector<vector<int>>::iterator pp;
vector<int>::iterator it;
for(pp=out.begin();pp<out.end();pp++)
{
for (it=(*pp).begin();it<(*pp).end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
}
return 0;
}
测试结果: