Iterate through different subset of size k

后端 未结 4 1594
-上瘾入骨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:19

    I like bit-twiddling for this problem. Sure, it limits you to only 32 elements in your vector, but it's still cool.

    First, given a bit mask, determine the next bitmask permutation (source):

    uint32_t next(uint32_t v) {
        uint32_t t = v | (v - 1);
        return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));  
    }
    

    Next, given a vector and a bitmask, give a new vector based on that mask:

    std::vector filter(const std::vector& v, uint32_t mask) {
        std::vector res;
        while (mask) {
            res.push_back(v[__builtin_ctz(mask)]);
            mask &= mask - 1;
        }   
        return res;
    }
    

    And with that, we just need a loop:

    std::set> get_subsets(const std::vector& arr, uint32_t k) {   
        std::set> s;
        uint32_t max = (1 << arr.size());
        for (uint32_t v = (1 << k) - 1; v < max; v = next(v)) {
            s.insert(filter(arr, v));
        }
        return s;
    }
    
    int main()
    {
        auto s = get_subsets({1, 2, 2, 3, 3, 3, 3}, 2);
        std::cout << s.size() << std::endl; // prints 5
    }
    

提交回复
热议问题