Iterate through different subset of size k

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

    The basic idea of this solution is a function like next_permutation but which generates the next ascending sequence of "digits". Here called ascend_ordered.

    template< class It >
    auto ascend_ordered( const int n_digits, const It begin, const It end )
        -> bool
    {
        using R_it = reverse_iterator< It >;
        const R_it r_begin  = R_it( end );
        const R_it r_end    = R_it( begin );
    
        int max_digit = n_digits - 1;
        for( R_it it = r_begin ; it != r_end; ++it )
        {
            if( *it < max_digit )
            {
                ++*it;
                const int n_further_items = it - r_begin;
                for( It it2 = end - n_further_items; it2 != end; ++it2 )
                {
                    *it2 = *(it2 - 1) + 1;
                }
                return true;
            }
            --max_digit;
        }
        return false;
    }
    

    Main program for the case at hand:

    auto main() -> int
    {
        vector a = {1,2,2,3,3,3,3};
        assert( is_sorted( begin( a ), end( a ) ) );
        const int k = 2;
        const int n = a.size();
        vector indices( k );
        iota( indices.begin(), indices.end(), 0 );      // Fill with 0, 1, 2 ...
        set> encountered;
        for( ;; )
        {
            vector current;
            for( int const i : indices ) { current.push_back( a[i] ); }
            if( encountered.count( current ) == 0 )
            {
                cout << "Indices " << indices << " -> values " << current << endl;
                encountered.insert( current );
            }
            if( not ascend_ordered( n, begin( indices ), end( indices ) ) )
            {
                break;
            }
        }
    }
    

    Supporting includes and i/o:

    #include 
    using std::is_sorted;
    
    #include 
    
    #include 
    using std::reverse_iterator;
    
    #include 
    using std::ostream; using std::cout; using std::endl;
    
    #include 
    using std::iota;
    
    #include 
    using std::set;
    
    #include 
    using std::begin; using std::end;
    
    #include 
    using std::vector;
    
    template< class Container, class Enable_if = typename Container::value_type >
    auto operator<<( ostream& stream, const Container& c )
        -> ostream&
    {
        stream << "{";
        int n_items_outputted = 0;
        for( const int x : c )
        {
            if( n_items_outputted >= 1 ) { stream << ", "; }
            stream << x;
            ++n_items_outputted;
        }
        stream << "}";
        return stream;
    }
    

提交回复
热议问题