Permutations unrank

蹲街弑〆低调 提交于 2021-02-10 04:21:50

问题


I know of an algorithm (it can be found online) to rank a permutation, i.e. given a permutation return the integer index into the list of lexicographically-sorted permutations, but I don't know any unrank algorithm that does the opposite: given an index i, return the i-th permutation in that lexicographic order.

Since I couldn't find any, can somebody please shed some light?


回答1:


Let's say you are permutating the letters (a, b, c).

There are 3×2×1=6 permutations. Out of these, a third starts with a and lexicographically precedes another third starting with b, preceding the last third starting with c.

For each of these thirds there are two halves, one starting with the first letter left after choosing the first, and the other with the second.

Each of these halves has only one element (the last letter).

So, given a set of three elements and an index between zero and five (let's say 3), we can divide (with reminder) by the size of each "third" to get the first letter. Now:

  • the set has size n=3
  • there are n!=6 permutations
  • there are n=3 groups of permutations which start with each of the n elements
  • each group has size n!/n = (n-1)! = 6/3 = 2 elements

To determine the index of the first element, we divide by 2 with remainder:

3÷2 = 1 rem 1

Since our set is (a,b,c), this tells us that the first letter is b.

Now, we can remove the letter b from the set, and use the reminder as the new index. We get the set (a, c) and index 1. Re-applying the algorithm,

  • the set has size n=2
  • there are n!=2 permutations
  • there are n=2 groups of permutations which start with each of the n elements
  • each group has size n!/n = (n-1)! = 2/2 = 1 element

To determine the index of the first element, we divide by 1 with remainder:

1÷1 = 1 rem 0

Since our set is (a,c), this tells us that the first second letter is c.

The third set is reduced to the singleton a and that's our third letter.

The permutation with index 3 is b,c,a.

Let's check it:

0 abc
1 acb
2 bac
3 bca <-- correct!
4 cab 
5 cba

So, putting this in a real algorithm and generalizing:

public string NthPerm(string set, int n)
{
    var res = "";
    while (set.Length > 0)
    {
        var setSize = Math.Factorial(set.Length-1);
        var index = n/setSize;

        res.Concat(set[index]);

        set = index > 0 ? set.Substring(0, index) : "" +
              index < set.Length-1 ? set.Substring(index+1) : "";

        n = n % setSize;
    }
    return res;
}


来源:https://stackoverflow.com/questions/31702845/permutations-unrank

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!