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 −
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