I have an array of n integers (not necessarily distinct!) and I would like to iterate over all subsets of size k. However I\'d like to exclude all duplicate subsets.
Unlike the previous answer, this is not as efficient and doesn't do anything as fancy as a lot of the bit twiddling. However it does not limit the size of your array or the size of the subset.
This solution uses std::next_permutation
to generate the combinations, and takes advantage of std::set
's uniqueness property.
#include
#include
#include
#include
#include
using namespace std;
std::set> getSubsets(const std::vector& vect, size_t numToChoose)
{
std::set> returnVal;
// return the whole thing if we want to
// choose everything
if (numToChoose >= vect.size())
{
returnVal.insert(vect);
return returnVal;
}
// set up bool vector for combination processing
std::vector bVect(vect.size() - numToChoose, false);
// stick the true values at the end of the vector
bVect.resize(bVect.size() + numToChoose, true);
// select where the ones are set in the bool vector and populate
// the combination vector
do
{
std::vector combination;
for (size_t i = 0; i < bVect.size() && combination.size() <= numToChoose; ++i)
{
if (bVect[i])
combination.push_back(vect[i]);
}
// sort the combinations
std::sort(combination.begin(), combination.end());
// insert this new combination in the set
returnVal.insert(combination);
} while (next_permutation(bVect.begin(), bVect.end()));
return returnVal;
}
int main()
{
std::vector myVect = {1,2,2,3,3,3,3};
// number to select
size_t numToSelect = 3;
// get the subsets
std::set> subSets = getSubsets(myVect, numToSelect);
// output the results
for_each(subSets.begin(), subSets.end(), [] (const vector& v)
{ cout << "subset "; copy(v.begin(), v.end(), ostream_iterator(cout, " ")); cout << "\n"; });
}
Live example: http://coliru.stacked-crooked.com/a/beb800809d78db1a
Basically we set up a bool vector and populate a vector with the values that correspond with the position of the true
items in the bool vector. Then we sort and insert this into a set. The std::next_permutation
shuffles the true
values in the bool array around and we just repeat.
Admittedly, not as sophisticated and more than likely slower than the previous answer, but it should do the job.