Ordered permutation of the list <Int>

For an ordered list of integers L = {1, 2, 3, 4} and the size of the permutation k,

I need to generate all the "ordered" permutations of length k having the first sequence = L [0].

In the above example, this should give the following results:

k = 1

= {1}

k = 2

= {1, 2}, {1, 3}, {1, 4}

k = 3

= {1, 2, 3}, {1, 2, 4}, {1, 3, 4}

k = 4

= {1, 2, 3, 4}

Here is what I came up with:

  • Assign permutations = Create all possible permutations L [1 ... n-1].
  • permutations.EliminateIfNotInOrder ().
  • Prepare L [0] with each sequence in permutations.

Is there a better way to generate all ordered permutations first and foremost without requiring the second step of exception?

0
1

, " " :

public static IEnumerable<T> Yield<T>( T value )
{
    yield return value;
}

public static IEnumerable<IEnumerable<T>> GetOrderedPermutations<T>( IEnumerable<T> source, int k )
{
    if( k == 0 ) return new[] { Enumerable.Empty<T>() };

    int length = source.Count();

    if( k == length ) return new[] { source };

    if( k > length ) return Enumerable.Empty<IEnumerable<T>>();

    return GetOrderedHelper<T>( source, k, length );
}

private static IEnumerable<IEnumerable<T>> GetOrderedHelper<T>( IEnumerable<T> source, int k, int length )
{
    if( k == 0 )
    {
        yield return Enumerable.Empty<T>();
        yield break;
    }
    int i = 0;
    foreach( var item in source )
    {
        if( i + k > length ) yield break;
        var permutations = GetOrderedHelper<T>( source.Skip( i + 1 ), k - 1, length - i );
        i++;

        foreach( var subPerm in permutations )
        {
            yield return Yield( item ).Concat( subPerm );
        }
    }
}

( ). , . , , , , :

var permutations = GetOrderedPermutations( source.Skip( 1 ), k - 1 )
    .Select( p => Yield( source.First() ).Concat( p ) );

: , k - 1, .

, :

k, k, k . . , . , . :

public static IEnumerable<IEnumerable<T>> GetOrderedPermutations<T>( IList<T> source, int k )
{
    if( k == 0 ) yield return Enumerable.Empty<T>();
    if( k == source.Count ) yield return source;
    if( k > source.Count ) yield break;
    var pointers = Enumerable.Range( 0, k ).ToArray();

    // The first element of our permutation can only be in the first
    // Count - k + 1 elements.  If it moves past here, we can't have
    // anymore permutations because there aren't enough items in the list.
    while( pointers[0] <= source.Count - k )
    {
        yield return pointers.Select( p => source[p] );
        // Increment the last pointer
        pointers[k - 1]++;

        // The i variable will keep track of which pointer
        // we need to increment.  Start it at the second to
        // last (since this is the one that we're going to
        // increment if the last pointer is past the end).
        int i = k - 2;
        while( pointers[k - 1] >= source.Count && i >= 0 )
        {
            // Okay, the last pointer was past the end, increment
            pointers[i]++;

            // Reset all the pointers after pointer i
            for( int j = i + 1; j < k; ++j )
            {
                pointers[j] = pointers[j - 1] + 1;
            }

            // If the last pointer is still past the end, we'll
            // catch it on the next go-around of this loop.
            // Decrement i so we move the previous pointer next time.

            --i;
        }
    }
}
+3

Source: https://habr.com/ru/post/1684914/


All Articles