Minimum number of prefix reversals to sort permutation of first N numbers
Given N numbers that have a permutation of first N numbers. In a single operation, any prefix can be reversed. The task is to find the minimum number of such operations such that the numbers in the array are in increasing order.
Examples:
Input : a[] = {3, 1, 2} Output : 2 Step1: Reverse the complete array a, a[] = {2, 1, 3} Step2: Reverse the prefix(0-1) in s, a[] = {1, 2, 3} Input : a[] = {1, 2, 4, 3} Output : 3 Step1: Reverse the complete array a, a[] = {3, 4, 2, 1} Step2: Reverse the prefix(0-1) in s, a[] = {4, 3, 2, 1} Step3: Reverse the complete array a, a[] = {1, 2, 3, 4}
The approach to solve this problem is to use BFS.
- Encode the given numbers in a string. Sort the array and encode it into a string destination.
- Then do a BFS from the initial permutation. Each time, check all permutations induced by reversing a prefix of current permutation.
- If it is not visited, put it into the queue with the count of reversals done.
- When the permutation of the encoded string is same as the destination string, return the numbers of reversals required to reach here.
- That is, all permutations of strings are done and the minimal of those is returned as the answer.
Below is the implementation of the above approach:
C++
// C++ program to find // minimum number of prefix reversals // to sort permutation of first N numbers #include <bits/stdc++.h> using namespace std; // Function to return the minimum prefix reversals int minimumPrefixReversals( int a[], int n) { string start = "" ; string destination = "" , t, r; for ( int i = 0; i < n; i++) { // converts the number to a character // and add to string start += to_string(a[i]); } sort(a, a + n); for ( int i = 0; i < n; i++) { destination += to_string(a[i]); } // Queue to store the pairs // of string and number of reversals queue<pair<string, int > > qu; pair<string, int > p; // Initially push the original string qu.push(make_pair(start, 0)); // if original string is the destination string if (start == destination) { return 0; } // iterate till queue is empty while (!qu.empty()) { // pair at the top p = qu.front(); // string t = p.first; // pop the top-most element qu.pop(); // perform prefix reversals for all index and push // in the queue and check for the minimal for ( int j = 2; j <= n; j++) { r = t; // reverse the string till prefix j reverse(r.begin(), r.begin() + j); // if after reversing the string from first i index // it is the destination if (r == destination) { return p.second + 1; } // push the number of reversals for string r qu.push(make_pair(r, p.second + 1)); } } } // Driver Code int main() { int a[] = { 1, 2, 4, 3 }; int n = sizeof (a) / sizeof (a[0]); // Calling function cout << minimumPrefixReversals(a, n); return 0; } |
Java
// Java program to find minimum // number of prefix reversals to // sort permutation of first N numbers import java.util.*; public class Main { // function to find minimum prefix reversal through BFS public static int minimumPrefixReversals( int [] a) { // size of array int n = a.length; // string for initial and goal nodes String start = "" , destination = "" ; // string for manipulation in while loop String original = "" ,modified = "" ; // node to store temporary values from front of queue Node temp = null ; // create the starting string for ( int i = 0 ; i < n; i++) start += a[i]; // sort the array and prepare final destination string Arrays.sort(a); for ( int i = 0 ; i < n; i++) destination += a[i]; // this queue will store all the BFS siblings Queue<Node> q = new LinkedList<>(); // place the starting node in queue q.add( new Node(start, 0 )); //base case:- if array is already sorted if (start == destination) return 0 ; // loop until the size of queue is empty while (q.size() != 0 ) { // put front node of queue in temporary variable temp = q.poll(); // store the original string at this step original = temp.string; for ( int j = 2 ; j <= n; j++) { // modified will be used to generate all // manipulation of original string // like if original = 1342 // modified = 3142 , 4312 , 2431 modified = original; // generate the permutation by reversing modified = reverse (modified , j); if (modified.equals(destination)) { // if string match then return // the height of the current node return temp.steps + 1 ; } // else put this node into queue q.add( new Node(modified,temp.steps + 1 )); } } // if no case match then default value return Integer.MIN_VALUE; } // function to reverse the string upto an index public static String reverse (String s , int index) { char temp []= s.toCharArray(); int i = 0 ; while (i < index) { char c = temp[i]; temp[i] = temp[index- 1 ]; temp[index- 1 ] = c; i++;index--; } return String.valueOf(temp); } // Driver code public static void main(String []args) { int a[] = new int []{ 1 , 2 , 4 , 3 }; System.out.println(minimumPrefixReversals(a)); } // Node class to store a combined set of values static class Node { public String string ; public int steps; public Node(String string, int steps) { this .string = string; this .steps= steps; } } } // This code is contributed by Sparsh Singhal |
C#
// C# program to find minimum // number of prefix reversals to // sort permutation of first N numbers using System; using System.Collections.Generic; class GFG { // Node class to store a combined set of values public class Node { public String str; public int steps; public Node(String str, int steps) { this .str = str; this .steps= steps; } } // function to find minimum prefix reversal through BFS public static int minimumPrefixReversals( int [] a) { // size of array int n = a.Length; // string for initial and goal nodes String start = "" , destination = "" ; // string for manipulation in while loop String original = "" , modified = "" ; // node to store temporary values // from front of queue Node temp = null ; // create the starting string for ( int i = 0; i < n; i++) start += a[i]; // sort the array and prepare // final destination string Array.Sort(a); for ( int i = 0; i < n; i++) destination += a[i]; // this queue will store all the BFS siblings Queue<Node> q = new Queue<Node>(); // place the starting node in queue q.Enqueue( new Node(start, 0)); //base case:- if array is already sorted if (start == destination) return 0; // loop until the size of queue is empty while (q.Count != 0) { // put front node of queue in temporary variable temp = q.Dequeue(); // store the original string at this step original = temp.str; for ( int j = 2; j <= n; j++) { // modified will be used to generate all // manipulation of original string // like if original = 1342 // modified = 3142 , 4312 , 2431 modified = original; // generate the permutation by reversing modified = reverse (modified , j); if (modified.Equals(destination)) { // if string match then return // the height of the current node return temp.steps + 1; } // else put this node into queue q.Enqueue( new Node(modified, temp.steps + 1)); } } // if no case match then default value return int .MinValue; } // function to reverse the string upto an index public static String reverse (String s, int index) { char []temp = s.ToCharArray(); int i = 0; while (i < index) { char c = temp[i]; temp[i] = temp[index - 1]; temp[index - 1] = c; i++;index--; } return String.Join( "" , temp); } // Driver code public static void Main(String []args) { int []a = new int []{1, 2, 4, 3}; Console.WriteLine(minimumPrefixReversals(a)); } } // This code is contributed by 29AjayKumar |
Javascript
<script> class Node { constructor(string,steps) { this .string = string; this .steps= steps; } } function minimumPrefixReversals(a) { // size of array let n = a.length; // string for initial and goal nodes let start = "" , destination = "" ; // string for manipulation in while loop let original = "" ,modified = "" ; // node to store temporary values from front of queue let temp = null ; // create the starting string for (let i = 0; i < n; i++) start += a[i]; // sort the array and prepare final destination string a.sort( function (a,b){ return a-b;}); for (let i = 0; i < n; i++) destination += a[i]; // this queue will store all the BFS siblings let q = []; // place the starting node in queue q.push( new Node(start, 0)); //base case:- if array is already sorted if (start == destination) return 0; // loop until the size of queue is empty while (q.length != 0) { // put front node of queue in temporary variable temp = q.shift(); // store the original string at this step original = temp.string; for (let j = 2; j <= n; j++) { // modified will be used to generate all // manipulation of original string // like if original = 1342 // modified = 3142 , 4312 , 2431 modified = original; // generate the permutation by reversing modified = reverse (modified , j); if (modified == (destination)) { // if string match then return // the height of the current node return temp.steps + 1; } // else put this node into queue q.push( new Node(modified,temp.steps + 1)); } } // if no case match then default value return Number.MIN_VALUE; } function reverse (s,index) { let temp = s.split( "" ); let i = 0; while (i < index) { let c = temp[i]; temp[i] = temp[index-1]; temp[index-1] = c; i++;index--; } return (temp).join( "" ); } let a = [1, 2, 4, 3]; document.write(minimumPrefixReversals(a)); // This code is contributed by rag2127 </script> |
Python3
# Python3 program to find # minimum number of prefix reversals # to sort permutation of [0] N numbers from queue import Queue # Function to return the minimum prefix reversals def minimumPrefixReversals( a, n): start = "" destination = "" for i in range (n): # converts the number to a character # and add to start + = str (a[i]) a.sort() for i in range (n): destination + = str (a[i]) # Queue to store the pairs # of and number of reversals qu = Queue() # Initially push the original qu.put((start, 0 )) # if original is the destination if (start = = destination) : return 0 # iterate till queue is empty while qu.not_empty : # pair at the top p = qu.get() # t = p[ 0 ] # perform prefix reversals for all index and push # in the queue and check for the minimal for j in range ( 2 ,n + 1 ) : r = t # reverse the till prefix j tmpR = list (r) tmpR[:j] = tmpR[j - 1 :: - 1 ] r = ''.join(tmpR) # if after reversing the from [0] i index # it is the destination if (r = = destination) : return p[ 1 ] + 1 # push the number of reversals for r qu.put((r, p[ 1 ] + 1 )) # Driver Code if __name__ = = '__main__' : a = [ 1 , 2 , 4 , 3 ] n = len (a) # Calling function print (minimumPrefixReversals(a, n)) |
Output:
3
Time Complexity: O(N! * N2)
Auxiliary Space: O(N!)
Please Login to comment...