Given a string containing all distinct characters, calculate its rank among all its lexicographically sorted permutations.

For example, consider the following lexicographically sorted permutations:

Input : CBA
Output: 6
Explanation: The rank of string DCBA in the lexicographically sorted permutations [ABC, ACB, BAC, BCA, CAB, CBA] is 6.

Practice this problem

A simple solution is to use std::next_permutation that generates the next greater lexicographic permutation of a string. The idea is to sort the string in ascending order and repeatedly calculate the lexicographic next permutation until the current permutation becomes equal to the given string.

C++


Download  Run Code

Output:

The lexicographic rank of DCBA is 24

The time complexity of the above solution is O(n.n!), where n is the length of the input string and doesn’t require any extra space.

 
Note that we can also use std::prev_permutation replacing std::next_permutation that generates the next smaller lexicographic permutation of a string. The implementation can be seen here.

 
We can improve worst-case time complexity to O(n2) by finding the total number of characters ranked before the current character in the string. Let c[i] denotes count of smaller characters than str[i] to the right of index i. Then for the string of length n, there will be

  • c[0]×(n-1)! permutations ranked above the string’s first character.
  • c[1]×(n-2)! permutations ranked above the second character in the string.
  • c[2]×(n-3)! permutations ranked above the third character in the string, and so on…

Following is the implementation in C++, Java, and Python based on the above idea:

C++


Download  Run Code

Output:

The lexicographic rank of DCBA is 24

Java


Download  Run Code

Output:

The lexicographic rank of DCBA is 24

Python


Download  Run Code

Output:

The lexicographic rank of DCBA is 24

The time complexity of the above solution is O(n2), where n is the length of the input string and doesn’t require any extra space.