Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Find n-th lexicographically permutation of a strings in Python
Finding the n-th lexicographically ordered permutation of a string is a classic combinatorial problem. Given a string with lowercase letters, we need to find the specific permutation that would appear at position n when all permutations are sorted alphabetically.
For example, if we have string = "pqr" and n = 3, all permutations in lexicographic order are: [pqr, prq, qpr, qrp, rpq, rqp]. The 3rd permutation is "qpr".
Algorithm Overview
The algorithm uses factorial number system to efficiently find the n-th permutation without generating all permutations ?
- Precompute factorials for quick access
- Count character frequencies in the string
- Build the result character by character using combinatorial math
- For each position, calculate how many permutations start with each possible character
Implementation
MAX_CHAR = 26
MAX_FACT = 20
def get_nth_permute(string, n):
# Precompute factorials
factorials = [1] * MAX_FACT
for i in range(1, MAX_FACT):
factorials[i] = factorials[i - 1] * i
size = len(string)
# Count character occurrences
occurrence = [0] * MAX_CHAR
for char in string:
occurrence[ord(char) - ord('a')] += 1
result = []
remaining = n
# Build result character by character
for pos in range(size):
for char_idx in range(MAX_CHAR):
if occurrence[char_idx] == 0:
continue
# Calculate permutations starting with this character
occurrence[char_idx] -= 1
perms_with_char = factorials[size - 1 - pos]
# Divide by factorial of remaining character counts
for j in range(MAX_CHAR):
if occurrence[j] > 0:
perms_with_char //= factorials[occurrence[j]]
if remaining <= perms_with_char:
# This is our character for current position
result.append(chr(char_idx + ord('a')))
break
else:
# Skip this character, reduce remaining count
remaining -= perms_with_char
occurrence[char_idx] += 1
return ''.join(result)
# Test the function
string = "pqr"
n = 3
result = get_nth_permute(string, n)
print(f"The {n}rd permutation of '{string}' is: {result}")
The 3rd permutation of 'pqr' is: qpr
How It Works
The algorithm works by determining each character of the result sequentially ?
- Factorial Calculation: We precompute factorials to quickly calculate the number of permutations
- Character Counting: Count frequency of each character in the input string
- Position-by-Position Building: For each position, we try characters in alphabetical order
- Combinatorial Math: Calculate how many permutations start with each character by using the multinomial coefficient
- Decision Making: If the remaining count is less than or equal to permutations with current character, we select it
Example with Multiple Characters
def demonstrate_permutations(string, n):
print(f"Finding {n}th permutation of '{string}'")
result = get_nth_permute(string, n)
print(f"Result: {result}")
print()
# Test with different examples
demonstrate_permutations("abc", 2)
demonstrate_permutations("aab", 3)
demonstrate_permutations("xyz", 5)
Finding 2th permutation of 'abc' Result: acb Finding 3th permutation of 'aab' Result: baa Finding 5th permutation of 'xyz' Result: zxy
Time and Space Complexity
Time Complexity: O(n × 26) where n is the length of the string, since we iterate through at most 26 characters for each position.
Space Complexity: O(1) as we use fixed-size arrays for character counting and factorial storage.
Conclusion
This algorithm efficiently finds the n-th lexicographic permutation using factorial number system and combinatorial mathematics. It avoids generating all permutations, making it suitable for large strings and high values of n.
