How to find Lexicographically previous permutation?
Given a word, find a lexicographically smaller permutation of it. For example, lexicographically smaller permutation of “4321” is “4312” and the next smaller permutation of “4312” is “4231”. If the string is sorted in ascending order, the next lexicographically smaller permutation doesn’t exist.
We have discussed next_permutation() which modifies a string so that it stores lexicographically smaller permutations. STL also provides std::prev_permutation. It returns ‘true’ if the function could rearrange the object as a lexicographically smaller permutation. Otherwise, it returns ‘false’.
C++
// C++ program to demonstrate working of // prev_permutation() #include <bits/stdc++.h> using namespace std; // Driver code int main() { string str = "4321" ; if (prev_permutation(str.begin(), str.end())) cout << "Previous permutation is " << str; else cout << "Previous permutation doesn't exist" ; return 0; } |
Python3
# Python implementation of above approach # Python program to demonstrate working of # prev_permutation() # import required module import itertools # Driver code if __name__ = = "__main__" : str = "4321" # using permutations function to get all # possible permutations permut = itertools.permutations( str ) # Using for loop to iterate through permutations # to find the previous permutation of str for val in permut: if "".join(val) = = str : print ( "Previous permutation is " , end = "") # Print the previous permutation print ("".join( next (permut))) break else : print ( "Previous permutation doesn't exist" ) # This code is contributed by codebraxnzt |
Java
// Java program for the above approach import java.util.Arrays; public class Main { // Driver Code public static void main(String[] args) { char [] str = { '4' , '3' , '2' , '1' }; if (prev_permutation(str)) { System.out.print( "Previous permutation is " ); System.out.println( new String(str)); } else { System.out.print( "Previous permutation doesn't exist" ); } } static boolean prev_permutation( char [] arr) { // Find the non-increasing suffix int n = arr.length; int i = n - 2 ; while (i >= 0 && arr[i] <= arr[i + 1 ]) { i--; } // If the entire array is non-increasing, it's the last permutation if (i < 0 ) { return false ; } // Find the rightmost element that's smaller than the pivot int j = n - 1 ; while (j > i && arr[j] >= arr[i]) { j--; } // Swap the pivot with the rightmost element that's smaller than the pivot swap(arr, i, j); // Reverse the suffix reverse(arr, i + 1 , n - 1 ); return true ; } // function for swapping static void swap( char [] arr, int i, int j) { char temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } // function for reversing static void reverse( char [] arr, int i, int j) { while (i < j) { swap(arr, i, j); i++; j--; } } } // This code is contributed by Prince Kumar |
Javascript
// JavaScript program to demonstrate working of prev_permutation() function prev_permutation(str) { // Convert the string to an array let arr = str.split( "" ); // Find the non-increasing suffix let i = arr.length - 1; while (i > 0 && arr[i - 1] <= arr[i]) { i--; } // If the entire array is non-increasing, it's the last permutation if (i <= 0) { return false ; } // Find the rightmost element that's smaller than the pivot let j = arr.length - 1; while (arr[j] >= arr[i - 1]) { j--; } // Swap the pivot with the rightmost element that's smaller than the pivot let temp = arr[i - 1]; arr[i - 1] = arr[j]; arr[j] = temp; // Reverse the suffix j = arr.length - 1; while (i < j) { temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; i++; j--; } // Convert the array back to a string and return return arr.join( "" ); } // Driver code let str = "4321" ; let result = prev_permutation(str); if (result) { console.log( "Previous permutation is " + result); } else { console.log( "Previous permutation doesn't exist" ); } // This code is contributed by adityashatmfh |
C#
using System; class Program { static string prev_permutation( string str) { // Convert the string to an array char [] arr = str.ToCharArray(); // Find the non-increasing suffix int i = arr.Length - 1; while (i > 0 && arr[i - 1] <= arr[i]) { i--; } // If the entire array is non-increasing, it's the // last permutation if (i <= 0) { return "Previous permutation doesn't exist" ; } // Find the rightmost element that's smaller than // the pivot int j = arr.Length - 1; while (arr[j] >= arr[i - 1]) { j--; } // Swap the pivot with the rightmost element that's // smaller than the pivot char temp = arr[i - 1]; arr[i - 1] = arr[j]; arr[j] = temp; // Reverse the suffix j = arr.Length - 1; while (i < j) { temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; i++; j--; } // Convert the array back to a string and return return new string (arr); } static void Main( string [] args) { string str = "4321" ; string result = prev_permutation(str); if (result != "Previous permutation doesn't exist" ) { Console.WriteLine( "Previous permutation is " + result); } else { Console.WriteLine(result); } } } |
Previous permutation is 4312
Time Complexity: O(N)m where N is the size of the given string.
Auxiliary Space: O(1), as constant space is used.
How to write our own prev_permutation()?
Below are steps to find the previous permutation:
- Find largest index i such that str[i – 1] > str[i].
- Find largest index j such that j >= i and str[j] < str[i – 1].
- Swap str[j] and str[i – 1].
- Reverse the sub-array starting at str[i].
Below is the implementation of above steps as follows:
C++
// C++ program to print all permutations with // duplicates allowed using prev_permutation() #include <bits/stdc++.h> using namespace std; // Function to compute the previous permutation bool prevPermutation(string& str) { // Find index of the last element of the string int n = str.length() - 1; // Find largest index i such that str[i - 1] > // str[i] int i = n; while (i > 0 && str[i - 1] <= str[i]) i--; // if string is sorted in ascending order // we're at the last permutation if (i <= 0) return false ; // Note - str[i..n] is sorted in ascending order // Find rightmost element's index that is less // than str[i - 1] int j = i - 1; while (j + 1 <= n && str[j + 1] < str[i - 1]) j++; // Swap character at i-1 with j swap(str[i - 1], str[j]); // Reverse the substring [i..n] reverse(str.begin() + i, str.end()); return true ; } // Driver code int main() { string str = "4321" ; if (prevPermutation(str)) cout << "Previous permutation is " << str; else cout << "Previous permutation doesn't exist" ; return 0; } |
Java
// Java program to print all // permutations with duplicates // allowed using prev_permutation() class GFG { // Function to compute // the previous permutation static boolean prevPermutation( char [] str) { // Find index of the last // element of the string int n = str.length - 1 ; // Find largest index i such // that str[i - 1] > str[i] int i = n; while (i > 0 && str[i - 1 ] <= str[i]) { i--; } // if string is sorted in // ascending order we're // at the last permutation if (i <= 0 ) { return false ; } // Note - str[i..n] is sorted // in ascending order Find // rightmost element's index // that is less than str[i - 1] int j = i - 1 ; while (j + 1 <= n && str[j + 1 ] <= str[i - 1 ]) { j++; } // Swap character at i-1 with j swap(str, i - 1 , j); // Reverse the substring [i..n] StringBuilder sb = new StringBuilder(String.valueOf(str)); sb.reverse(); str = sb.toString().toCharArray(); return true ; } static String swap( char [] ch, int i, int j) { char temp = ch[i]; ch[i] = ch[j]; ch[j] = temp; return String.valueOf(ch); } // Driver code public static void main(String[] args) { char [] str = "4321" .toCharArray(); if (prevPermutation(str)) { System.out.println( "Previous permutation is " + String.valueOf(str)); } else { System.out.println( "Previous permutation" + "doesn't exist" ); } } } // This code is contributed by 29AjayKumar |
Python
# Python 3 program to # print all permutations with # duplicates allowed # using prev_permutation() # Function to compute the # previous permutation def prevPermutation( str ): # Find index of the last element # of the string n = len ( str ) - 1 # Find largest index i such that # str[i - 1] > str[i] i = n while (i > 0 and str [i - 1 ] < = str [i]): i - = 1 # if string is sorted in ascending order # we're at the last permutation if (i < = 0 ): return False , str # Note - str[i..n] is sorted in # ascending order # Find rightmost element's index # that is less than str[i - 1] j = i - 1 while (j + 1 < = n and str [j + 1 ] < str [i - 1 ]): j + = 1 # Swap character at i-1 with j str = list ( str ) temp = str [i - 1 ] str [i - 1 ] = str [j] str [j] = temp str = ''.join( str ) # Reverse the substring [i..n] str [i:: - 1 ] return True , str # Driver code if __name__ = = '__main__' : str = "133" b, str = prevPermutation( str ) if (b = = True ): print ( "Previous permutation is" , str ) else : print ( "Previous permutation doesn't exist" ) # This code is contributed by # Sanjit_Prasad |
C#
// C# program to print all // permutations with duplicates // allowed using prev_permutation() using System; class GFG { // Function to compute // the previous permutation static Boolean prevPermutation( char [] str) { // Find index of the last // element of the string int n = str.Length - 1; // Find largest index i such // that str[i - 1] > str[i] int i = n; while (i > 0 && str[i - 1] <= str[i]) { i--; } // if string is sorted in // ascending order we're // at the last permutation if (i <= 0) { return false ; } // Note - str[i..n] is sorted // in ascending order Find // rightmost element's index // that is less than str[i - 1] int j = i - 1; while (j + 1 <= n && str[j + 1] <= str[i - 1]) { j++; } // Swap character at i-1 with j swap(str, i - 1, j); // Reverse the substring [i..n] String sb = String.Join( "" , str); sb = reverse(sb); str = sb.ToString().ToCharArray(); return true ; } static String swap( char [] ch, int i, int j) { char temp = ch[i]; ch[i] = ch[j]; ch[j] = temp; return String.Join( "" , ch); } static String reverse(String input) { char [] temparray = input.ToCharArray(); int left, right = 0; right = temparray.Length - 1; for (left = 0; left < right; left++, right--) { // Swap values of left and right char temp = temparray[left]; temparray[left] = temparray[right]; temparray[right] = temp; } return String.Join( "" , temparray); } // Driver code public static void Main(String[] args) { char [] str = "4321" .ToCharArray(); if (prevPermutation(str)) { Console.WriteLine( "Previous permutation is " + String.Join( "" , str)); } else { Console.WriteLine( "Previous permutation" + "doesn't exist" ); } } } // This code is contributed by Rajput-Ji |
Javascript
// Javascript program to print all // permutations with duplicates // allowed using prev_permutation() // Function to compute // the previous permutation function prevPermutation(str){ // Find index of the last // element of the string let n = str.length - 1; // Find largest index i such // that str[i - 1] > str[i] let i = n; while (i > 0 && str[i - 1] <= str[i]){ i--; } // If string is sorted in // ascending order we're // at the last permutation if (i <= 0){ return false ; } // Note - str[i..n] is sorted // in ascending order Find // rightmost element's index // that is less than str[i - 1] let j = i - 1; while (j + 1 <= n && str[j + 1] < str[i - 1]){ j++; } // Swap character at i-1 with j const temper = str[i - 1]; str[i - 1] = str[j]; str[j] = temper; // Reverse the substring [i..n] let size = n-i+1; for (let idx = 0; idx < Math.floor(size / 2); idx++) { let temp = str[idx + i]; str[idx + i] = str[n - idx]; str[n - idx] = temp; } return true ; } // Driver code let str = "4321" .split( "" ); if (prevPermutation(str)) { console.log( "Previous permutation is " + (str).join( "" )); } else { console.log( "Previous permutation" + "doesn't exist" ); } // This code is contributed by Gautam goel (gautamgoel962) |
Previous permutation is 4312
Time Complexity: O(N)m where N is the size of the given string.
Auxiliary Space: O(1), as constant space is used.
This article is contributed by Aarti_Rathi and Aditya Goel. If you like GeeksforGeeks and would like to contribute, you can also write an article and mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or if you want to share more information about the topic discussed above.
Please Login to comment...