(Any Language) Find all permutations of elements i

2019-03-04 04:17发布

问题:

I was asked this question in a Lab session today.

We can imagine a vector containing the elements 1 ... N - 1, with a length N. Is there an algorithmic (systematic) method of generating all permutations, or orders of the elements in the vector. One proposed method was to swap random elements. Obviously this would work provided all previously generated permutations were stored for future reference, however this is obviously a very inefficient method, both space wise and time wise.

The reason for doing this by the way is to remove special elements (eg elements which are zero) from special positions in the vector, where such an element is not allowed. Therefore the random method isn't quite so ridiculous, but imagine the case where the number of elements is large and the number of possible permutations (which are such that there are no "special elements" in any of the "special positions") is low.

We tried to work through this problem for the case of N = 5:

x = [1, 2, 3, 4, 5]

First, swap elements 4 and 5:

x = [1, 2, 3, 5, 4]

Then swap 3 and 5:

x = [1, 2, 4, 5, 3]

Then 3 and 4:

x = [1, 2, 5, 4, 3]

Originally we thought using two indices, ix and jx, might be a possible solution. Something like:

ix = 0;
jx = 0;

for(;;)
{
    ++ ix;

    if(ix >= N)
    {
        ix = 0;
        ++ jx;

        if(jx >= N)
        {
            break; // We have got to an exit condition, but HAVENT got all permutations
        }
    }

    swap elements at positions ix and jx

    print out the elements
}

This works for the case where N = 3. However it doesn't work for higher N. We think that this sort of approach might be along the right lines. We were trying to extend to a method where 3 indexes are used, for some reason we think that might be the solution: Using a 3rd index to mark a position in the vector where the index ix starts or ends. But we got stuck, and decided to ask the SO community for advice.

回答1:

One way to do this is to, for the first character e:

  • First recurse on the next element
  • Then, for each element e2 after e:
    • Swap e and e2
    • Then recurse on the next element
    • And undo the swap

Pseudo-code:

permutation(input, 0)

permutation(char[] array, int start)
    if (start == array.length)
        print array

    for (int i = start; i < array.length; i++)
        swap(array[start], array[i])
        permutation(array, start+1)
        swap(array[start], array[i])

With the main call of this function, it will try each character in the first position and then recurse. Simply looping over all the characters works here because we undo each swap afterwards, so after the recursive call returns, we're guaranteed to be back where we started.

And then, for each of those recursive calls, it tries each remaining character in the second position. And so on.

Java live demo.