Given a string of length m containing lowercase alphabets only. We need to find the n-th permutation of string lexicographic ally.
Examples:
Input: str[] = "abc", n = 3
Output: Result = "bac"
All possible permutation in
sorted order: abc, acb, bac,
bca, cab, cba
Input: str[] = "aba", n = 2
Output: Result = "aba"
All possible permutation
in sorted order: aab, aba, baa
Naive Approach: Find lexicographically n-th permutation using STL.
Efficient Approach: Mathematical concept for solving this problem.
- The total number of permutation of a string formed by N characters(all distinct) is N!
- The Total number of permutation of a string formed by N characters (where the frequency of character C1 is M1, C2 is M2… and so the frequency of character Ck is Mk) is N!/(M1! * M2! *….Mk!).
- The total number of permutation of a string formed by N characters(all distinct) after fixing the first character is (N-1)!
The following steps can be followed to reach the solution.
- Count the frequencies of all characters in an array.
- Now from the first smallest character present in the string(smallest index i such that freq[i] > 0), compute the number of maximum permutation possible after setting that particular i-th character as the first character.
- If this sum value is more than given n, then set that character as the first result output character, and decrement freq[i]. Continue the same for the remaining n-1 characters.
- On the other hand, if the count is less than the required n, then iterate for the next character in the frequency table and update the count over and over again until we find a character that produces a count greater than the required n.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
#define ll long long int
const int MAX_CHAR = 26;
const int MAX_FACT = 20;
ll fact[MAX_FACT];
void precomputeFactorials()
{
fact[0] = 1;
for ( int i = 1; i < MAX_FACT; i++)
fact[i] = fact[i - 1] * i;
}
void nPermute( char str[], int n)
{
precomputeFactorials();
int len = strlen (str);
int freq[MAX_CHAR] = { 0 };
for ( int i = 0; i < len; i++)
freq[str[i] - 'a' ]++;
char out[MAX_CHAR];
int sum = 0;
int k = 0;
while (sum != n) {
sum = 0;
for ( int i = 0; i < MAX_CHAR; i++) {
if (freq[i] == 0)
continue ;
freq[i]--;
int xsum = fact[len - 1 - k];
for ( int j = 0; j < MAX_CHAR; j++)
xsum /= fact[freq[j]];
sum += xsum;
if (sum >= n) {
out[k++] = i + 'a' ;
n -= (sum - xsum);
break ;
}
if (sum < n)
freq[i]++;
}
}
for ( int i = MAX_CHAR - 1;
k < len && i >= 0; i--)
if (freq[i]) {
out[k++] = i + 'a' ;
freq[i++]--;
}
out[k] = '\0' ;
cout << out;
}
int main()
{
int n = 2;
char str[] = "geeksquiz" ;
nPermute(str, n);
return 0;
}
|
Java
public class PermuteString {
final static int MAX_CHAR = 26 ;
final static int MAX_FACT = 20 ;
static long fact[] = new long [MAX_FACT];
static void precomputeFactorirals()
{
fact[ 0 ] = 1 ;
for ( int i = 1 ; i < MAX_FACT; i++)
fact[i] = fact[i - 1 ] * i;
}
static void nPermute(String str, int n)
{
precomputeFactorirals();
int len = str.length();
int freq[] = new int [MAX_CHAR];
for ( int i = 0 ; i < len; i++)
freq[str.charAt(i) - 'a' ]++;
String out = "" ;
int sum = 10 ;
int k = 0 ;
while (sum >= n) {
for ( int i = 0 ; i < MAX_CHAR; i++) {
if (freq[i] == 0 )
continue ;
freq[i]--;
sum = 0 ;
int xsum = ( int )fact[len - 1 - k];
for ( int j = 0 ; j < MAX_CHAR; j++)
xsum /= fact[freq[j]];
sum += xsum;
if (sum >= n) {
out += ( char )(i + 'a' );
k++;
n -= (sum - xsum);
break ;
}
if (sum < n)
freq[i]++;
}
}
for ( int i = MAX_CHAR - 1 ;
k < len && i >= 0 ; i--)
if (freq[i] != 0 ) {
out += ( char )(i + 'a' );
freq[i++]--;
}
System.out.println(out);
}
public static void main(String[] args)
{
int n = 2 ;
String str = "geeksquiz" ;
nPermute(str, n);
}
}
|
Python3
MAX_CHAR = 26
MAX_FACT = 20
fact = [ None ] * (MAX_FACT)
def precomputeFactorials():
fact[ 0 ] = 1
for i in range ( 1 , MAX_FACT):
fact[i] = fact[i - 1 ] * i
def nPermute(string, n):
precomputeFactorials()
length = len (string)
freq = [ 0 ] * (MAX_CHAR)
for i in range ( 0 , length):
freq[ ord (string[i]) - ord ( 'a' )] + = 1
out = [ None ] * (MAX_CHAR)
Sum , k = 0 , 0
while Sum ! = n:
Sum = 0
for i in range ( 0 , MAX_CHAR):
if freq[i] = = 0 :
continue
freq[i] - = 1
xsum = fact[length - 1 - k]
for j in range ( 0 , MAX_CHAR):
xsum = xsum / / fact[freq[j]]
Sum + = xsum
if Sum > = n:
out[k] = chr (i + ord ( 'a' ))
n - = Sum - xsum
k + = 1
break
if Sum < n:
freq[i] + = 1
i = MAX_CHAR - 1
while k < length and i > = 0 :
if freq[i]:
out[k] = chr (i + ord ( 'a' ))
freq[i] - = 1
i + = 1
k + = 1
i - = 1
print (''.join(out[:k]))
if __name__ = = "__main__" :
n = 2
string = "geeksquiz"
nPermute(string, n)
|
C#
using System;
public class GFG {
static int MAX_CHAR = 26;
static int MAX_FACT = 20;
static long [] fact = new long [MAX_FACT];
static void precomputeFactorirals()
{
fact[0] = 1;
for ( int i = 1; i < MAX_FACT; i++)
fact[i] = fact[i - 1] * i;
}
static void nPermute(String str, int n)
{
precomputeFactorirals();
int len = str.Length;
int [] freq = new int [MAX_CHAR];
for ( int i = 0; i < len; i++)
freq[str[i] - 'a' ]++;
string ou = "" ;
int sum = 10;
int k = 0;
while (sum >= n) {
for ( int i = 0; i < MAX_CHAR; i++) {
if (freq[i] == 0)
continue ;
freq[i]--;
sum = 0;
int xsum = ( int )fact[len - 1 - k];
for ( int j = 0; j < MAX_CHAR; j++)
xsum /= ( int )(fact[freq[j]]);
sum += xsum;
if (sum >= n) {
ou += ( char )(i + 'a' );
k++;
n -= (sum - xsum);
break ;
}
if (sum < n)
freq[i]++;
}
}
for ( int i = MAX_CHAR - 1; k < len && i >= 0; i--)
if (freq[i] != 0) {
ou += ( char )(i + 'a' );
freq[i++]--;
}
Console.Write(ou);
}
public static void Main()
{
int n = 2;
String str = "geeksquiz" ;
nPermute(str, n);
}
}
|
Javascript
<script>
let MAX_CHAR = 26;
let MAX_FACT = 20;
let fact= new Array(MAX_FACT);
function precomputeFactorirals()
{
fact[0] = 1;
for (let i = 1; i < MAX_FACT; i++)
fact[i] = fact[i - 1] * i;
}
function nPermute(str,n)
{
precomputeFactorirals();
let len = str.length;
let freq = new Array(MAX_CHAR);
for (let i=0;i<MAX_CHAR;i++)
{
freq[i]=0;
}
for (let i = 0; i < len; i++)
freq[str[i].charCodeAt(0) - 'a' .charCodeAt(0)]++;
let out = "" ;
let sum = 10;
let k = 0;
while (sum >= n) {
for (let i = 0; i < MAX_CHAR; i++) {
if (freq[i] == 0)
continue ;
freq[i]--;
sum = 0;
let xsum = fact[len - 1 - k];
for (let j = 0; j < MAX_CHAR; j++)
xsum = Math.floor(xsum/fact[freq[j]]);
sum += xsum;
if (sum >= n) {
out += String.fromCharCode(i + 'a' .charCodeAt(0));
k++;
n -= (sum - xsum);
break ;
}
if (sum < n)
freq[i]++;
}
}
for (let i = MAX_CHAR - 1;
k < len && i >= 0; i--)
if (freq[i] != 0) {
out += String.fromCharCode(i + 'a' .charCodeAt(0));
freq[i++]--;
}
document.write(out);
}
let n = 2;
let str = "geeksquiz" ;
nPermute(str, n);
</script>
|
Complexity Analysis:
- Time Complexity: O(N^2), where N is the length of the input string.
- Auxiliary Space: O(MAX_CHAR), which is the size of the freq and out arrays
If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
24 Mar, 2023
Like Article
Save Article