Iterate through different subset of size k

后端 未结 4 1589
-上瘾入骨i
-上瘾入骨i 2021-01-19 06:19

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.

4条回答
  •  有刺的猬
    2021-01-19 07:00

    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.

提交回复
热议问题