Find n-th lexicographically permutation of a strings in Python


Suppose we have a string whose length is m, and this string is containing only lowercase letters, we have to find the n-th permutation of string lexicographically.

So, if the input is like string = "pqr", n = 3, then the output will be "qpr" as all permutations are [pqr, prq, qpr, qrp, rpq, rqp], they are in sorted order.

To solve this, we will follow these steps −

  • MAX_CHAR := 26

  • MAX_FACT := 20

  • factorials := an array of size MAX_FACT

  • factorials[0] := 1

  • for i in range 1 to MAX_FACT, do

    • factorials[i] := factorials[i - 1] * i

  • size := size of string

  • occurrence := an array of size MAX_CHAR, fill with 0

  • for i in range 0 to size, do

    • occurrence[ASCII of (string[i]) - ASCII of ('a') ] := occurrence[ASCII of (string[i]) - ASCII of ('a') ] + 1

  • res := an array of size MAX_CHAR

  • Sum := 0, k := 0

  • while Sum is not same as n, do

    • Sum := 0

    • for i in range 0 to MAX_CHAR, do

      • if occurrence[i] is same as 0, then

        • go for next iteration

      • occurrence[i] := occurrence[i] - 1

      • temp_sum := factorials[size - 1 - k]

      • for j in range 0 to MAX_CHAR, do

        • temp_sum := temp_sum / factorials[occurrence[j]] (integer division)

      • Sum := Sum + temp_sum

      • if Sum >= n, then

        • res[k] := character from ASCII code (i + ASCII of('a'))

        • n := n - Sum - temp_sum

        • k := k + 1

        • come out from the loop

      • if Sum < n, then

        • occurrence[i] := occurrence[i] + 1

  • i := MAX_CHAR-1

  • while k < size and i >= 0, do

    • if occurrence[i] is non-zero, then

      • res[k] := character from ASCII code (i + ASCII of('a'))

      • occurrence[i] := occurrence[i] - 1

      • i := i + 1

      • k := k + 1

    • i := i - 1

  • return make string from res from index 0 to (k - 1)

Example

Let us see the following implementation to get better understanding −

 Live Demo

MAX_CHAR = 26
MAX_FACT = 20
factorials = [None] * (MAX_FACT)
def get_nth_permute(string, n):
   factorials[0] = 1
   for i in range(1, MAX_FACT):
      factorials[i] = factorials[i - 1] * i
   size = len(string)
   occurrence = [0] * (MAX_CHAR)
   for i in range(0, size):
      occurrence[ord(string[i]) - ord('a')] += 1
   res = [None] * (MAX_CHAR)
   Sum = 0
   k = 0
   while Sum != n:
      Sum = 0
      for i in range(0, MAX_CHAR):
         if occurrence[i] == 0:
            continue
         occurrence[i] -= 1
         temp_sum = factorials[size - 1 - k]
         for j in range(0, MAX_CHAR):
            temp_sum = temp_sum // factorials[occurrence[j]]
         Sum += temp_sum
         if Sum >= n:
            res[k] = chr(i + ord('a'))
            n -= Sum - temp_sum
            k += 1
            break
         if Sum < n:
            occurrence[i] += 1
   i = MAX_CHAR-1
   while k < size and i >= 0:
      if occurrence[i]:
         res[k] = chr(i + ord('a'))
         occurrence[i] -= 1
         i += 1
         k += 1
      i -= 1
   return ''.join(res[:k])

n = 3
string = "pqr"
print(get_nth_permute(string, n))

Input

"pqr"

Output

qpr

Updated on: 25-Aug-2020

139 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements