Given an array arr[] of size N, where arr[i] denotes the number of elements on the left that are greater than the ith element in the original permutation. The task is to find the original permutation of [1, N] for which given inversion array arr[] holds valid.
Examples:
Input: arr[] = {0, 1, 1, 0, 3}
Output: 4 1 3 5 2
Explanation:
The original permutation is ans[] = {4, 1, 3, 5, 2}
ans[0] = 4.
ans[1] = 1. Since {4} exists on its left, which exceeds 1, arr[1] = 1 holds valid.
ans[2] = 3. Since {4} exists on its left, which exceeds 3, arr[2] = 1 holds valid.
ans[3] = 5. Since no elements on its left exceeds 5, arr[3] = 0 holds valid.
ans[4] = 2. Since {4, 3, 5} exists on its left, which exceeds 2, arr[4] = 3 holds valid.Input: arr[] = {0, 1, 2}
Output: 3 2 1
Naive Approach: The simplest approach is to generate all the permutations of N number and for each permutation, check if its elements satisfy the inversions given by the array arr[]. If such permutation is found, print it.
Time Complexity: O(N!)
Auxiliary Space: O(N)
Efficient Approach: To optimize the above approach, the idea is to use a Segment Tree. Follow the below steps to solve the problem:
- Build a segment tree of size N and initialize all leaf nodes with value 1.
- Traverse the given array from right to left. For example, if the current index is N – 1, i.e, none of the elements are visited. So, the arr[i] is the number of elements that should be greater than the element which has to be at this position. So, the answer for this element is the (N – arr[N – 1])th element in the segment tree corresponds to that element. After that, mark that element as 0 to avoid its counting again.
- Similarly, find (i + 1 – arr[i])th element in the segment tree, for each i from (N – 1) to 0.
- After finding the answer for arr[i], let it be temp, store it in some array ans[], and update the node having index temp with 0.
- Finally, print the answer array ans[] in reversed order as the original permutation.
Below is the implementation of the above approach:
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; const int MAXX = 100; // Declaring segment tree int st[4 * MAXX]; // Function to initialize segment tree // with leaves filled with ones void build( int x, int lx, int rx) { // Base Case if (rx - lx == 1) { st[x] = 1; return ; } // Split into two halves int m = (lx + rx) / 2; // Build the left subtree build(x * 2 + 1, lx, m); // Build the right subtree build(x * 2 + 2, m, rx); // Combining both left and right // subtree to parent node st[x] = st[x * 2 + 1] + st[x * 2 + 2]; return ; } // Function to make index x to 0 // and then update segment tree void update( int i, int x, int lx, int rx) { // Base Case if (rx - lx == 1) { st[x] = 0; return ; } // Split into two halves int m = (lx + rx) / 2; // Update Query if (i < m) update(i, x * 2 + 1, lx, m); else update(i, x * 2 + 2, m, rx); // Combining both left and right // subtree to parent node st[x] = st[x * 2 + 1] + st[x * 2 + 2]; return ; } // Function to find the Kth element int getans( int x, int lx, int rx, int k, int n) { // Base Condition if (rx - lx == 1) { if (st[x] == k) return lx; return n; } // Split into two halves int m = (lx + rx) / 2; // Check if kth one is in left subtree // or right subtree of current node if (st[x * 2 + 1] >= k) return getans(x * 2 + 1, lx, m, k, n); else return getans(x * 2 + 2, m, rx, k - st[x * 2 + 1], n); } // Function to generate the original // permutation void getPermutation( int inv[], int n) { // Build segment tree build(0, 0, n); // Stores the original permutation vector< int > ans; for ( int i = n - 1; i >= 0; i--) { // Find kth one int temp = getans(0, 0, n, st[0] - inv[i], n); // Answer for arr[i] ans.push_back(temp + 1); // Setting found value back to 0 update(max(0, temp), 0, 0, n); } // Print the permutation for ( int i = n - 1; i >= 0; i--) cout << ans[i] << " " ; return ; } // Driver Code int main() { // Given array int inv[] = { 0, 1, 1, 0, 3 }; // Length of the given array int N = sizeof (inv) / sizeof (inv[0]); // Function Call getPermutation(inv, N); return 0; } |
Java
// Java program for the above approach import java.util.*; class GFG{ static int MAXX = 100 ; // Declaring segment tree static int []st = new int [ 4 * MAXX]; // Function to initialize segment tree // with leaves filled with ones static void build( int x, int lx, int rx) { // Base Case if (rx - lx == 1 ) { st[x] = 1 ; return ; } // Split into two halves int m = (lx + rx) / 2 ; // Build the left subtree build(x * 2 + 1 , lx, m); // Build the right subtree build(x * 2 + 2 , m, rx); // Combining both left and right // subtree to parent node st[x] = st[x * 2 + 1 ] + st[x * 2 + 2 ]; return ; } // Function to make index x to 0 // and then update segment tree static void update( int i, int x, int lx, int rx) { // Base Case if (rx - lx == 1 ) { st[x] = 0 ; return ; } // Split into two halves int m = (lx + rx) / 2 ; // Update Query if (i < m) update(i, x * 2 + 1 , lx, m); else update(i, x * 2 + 2 , m, rx); // Combining both left and right // subtree to parent node st[x] = st[x * 2 + 1 ] + st[x * 2 + 2 ]; return ; } // Function to find the Kth element static int getans( int x, int lx, int rx, int k, int n) { // Base Condition if (rx - lx == 1 ) { if (st[x] == k) return lx; return n; } // Split into two halves int m = (lx + rx) / 2 ; // Check if kth one is in left subtree // or right subtree of current node if (st[x * 2 + 1 ] >= k) return getans(x * 2 + 1 , lx, m, k, n); else return getans(x * 2 + 2 , m, rx, k - st[x * 2 + 1 ], n); } // Function to generate the original // permutation static void getPermutation( int inv[], int n) { // Build segment tree build( 0 , 0 , n); // Stores the original permutation Vector<Integer> ans = new Vector<Integer>(); for ( int i = n - 1 ; i >= 0 ; i--) { // Find kth one int temp = getans( 0 , 0 , n, st[ 0 ] - inv[i], n); // Answer for arr[i] ans.add(temp + 1 ); // Setting found value back to 0 update(Math.max( 0 , temp), 0 , 0 , n); } // Print the permutation for ( int i = n - 1 ; i >= 0 ; i--) System.out.print(ans.get(i) + " " ); return ; } // Driver Code public static void main(String args[]) { // Given array int inv[] = { 0 , 1 , 1 , 0 , 3 }; // Length of the given array int N = inv.length; // Function Call getPermutation(inv, N); } } // This code is contributed by SURENDRA_GANGWAR |
Python3
# Python3 program for the above approach MAXX = 100 # Declaring segment tree st = [ 0 ] * ( 4 * MAXX) # Function to initialize segment tree # with leaves filled with ones def build(x, lx, rx): # Base Case if (rx - lx = = 1 ): st[x] = 1 return # Split into two halves m = (lx + rx) / / 2 # Build the left subtree build(x * 2 + 1 , lx, m) # Build the right subtree build(x * 2 + 2 , m, rx) # Combining both left and right # subtree to parent node st[x] = st[x * 2 + 1 ] + st[x * 2 + 2 ] return # Function to make index x to 0 # and then update segment tree def update(i, x, lx, rx): # Base Case if (rx - lx = = 1 ): st[x] = 0 return # Split into two halves m = (lx + rx) / / 2 # Update Query if (i < m): update(i, x * 2 + 1 , lx, m) else : update(i, x * 2 + 2 , m, rx) # Combining both left and right # subtree to parent node st[x] = st[x * 2 + 1 ] + st[x * 2 + 2 ] return # Function to find the Kth element def getans(x, lx, rx, k, n): # Base Condition if (rx - lx = = 1 ): if (st[x] = = k): return lx return n # Split into two halves m = (lx + rx) / / 2 # Check if kth one is in left subtree # or right subtree of current node if (st[x * 2 + 1 ] > = k): return getans(x * 2 + 1 , lx, m, k, n) else : return getans(x * 2 + 2 , m, rx, k - st[x * 2 + 1 ], n) # Function to generate the original # permutation def getPermutation(inv, n): # Build segment tree build( 0 , 0 , n) # Stores the original permutation ans = [] for i in range (n - 1 , - 1 , - 1 ): # Find kth one temp = getans( 0 , 0 , n, st[ 0 ] - inv[i], n) # Answer for arr[i] ans.append(temp + 1 ) # Setting found value back to 0 update( max ( 0 , temp), 0 , 0 , n) # Print the permutation for i in range (n - 1 , - 1 , - 1 ): print (ans[i], end = " " ) return # Driver Code if __name__ = = '__main__' : # Given array inv = [ 0 , 1 , 1 , 0 , 3 ] # Length of the given array N = len (inv) # Function Call getPermutation(inv, N) # This code is contributed by mohit kumar 29 |
C#
// C# program for the above approach using System; using System.Collections.Generic; class GFG{ static int MAXX = 100; // Declaring segment tree static int []st = new int [4 * MAXX]; // Function to initialize segment tree // with leaves filled with ones static void build( int x, int lx, int rx) { // Base Case if (rx - lx == 1) { st[x] = 1; return ; } // Split into two halves int m = (lx + rx) / 2; // Build the left subtree build(x * 2 + 1, lx, m); // Build the right subtree build(x * 2 + 2, m, rx); // Combining both left and right // subtree to parent node st[x] = st[x * 2 + 1] + st[x * 2 + 2]; return ; } // Function to make index x to 0 // and then update segment tree static void update( int i, int x, int lx, int rx) { // Base Case if (rx - lx == 1) { st[x] = 0; return ; } // Split into two halves int m = (lx + rx) / 2; // Update Query if (i < m) update(i, x * 2 + 1, lx, m); else update(i, x * 2 + 2, m, rx); // Combining both left and right // subtree to parent node st[x] = st[x * 2 + 1] + st[x * 2 + 2]; return ; } // Function to find the Kth element static int getans( int x, int lx, int rx, int k, int n) { // Base Condition if (rx - lx == 1) { if (st[x] == k) return lx; return n; } // Split into two halves int m = (lx + rx) / 2; // Check if kth one is in left subtree // or right subtree of current node if (st[x * 2 + 1] >= k) return getans(x * 2 + 1, lx, m, k, n); else return getans(x * 2 + 2, m, rx, k - st[x * 2 + 1], n); } // Function to generate the original // permutation static void getPermutation( int []inv, int n) { // Build segment tree build(0, 0, n); // Stores the original permutation List< int > ans = new List< int >(); for ( int i = n - 1; i >= 0; i--) { // Find kth one int temp = getans(0, 0, n, st[0] - inv[i], n); // Answer for arr[i] ans.Add(temp + 1); // Setting found value back to 0 update(Math.Max(0, temp), 0, 0, n); } // Print the permutation for ( int i = n - 1; i >= 0; i--) Console.Write(ans[i] + " " ); return ; } // Driver Code public static void Main(String []args) { // Given array int []inv = { 0, 1, 1, 0, 3 }; // Length of the given array int N = inv.Length; // Function Call getPermutation(inv, N); } } // This code is contributed by Amit Katiyar |
Javascript
<script> // Javascript program for the above approach let MAXX = 100; // Declaring segment tree let st = new Array(4 * MAXX); // Function to initialize segment tree // with leaves filled with ones function build(x, lx, rx) { // Base Case if (rx - lx == 1) { st[x] = 1; return ; } // Split into two halves let m = parseInt((lx + rx) / 2, 10); // Build the left subtree build(x * 2 + 1, lx, m); // Build the right subtree build(x * 2 + 2, m, rx); // Combining both left and right // subtree to parent node st[x] = st[x * 2 + 1] + st[x * 2 + 2]; return ; } // Function to make index x to 0 // and then update segment tree function update(i, x, lx, rx) { // Base Case if (rx - lx == 1) { st[x] = 0; return ; } // Split into two halves let m = parseInt((lx + rx) / 2, 10); // Update Query if (i < m) update(i, x * 2 + 1, lx, m); else update(i, x * 2 + 2, m, rx); // Combining both left and right // subtree to parent node st[x] = st[x * 2 + 1] + st[x * 2 + 2]; return ; } // Function to find the Kth element function getans(x, lx, rx, k, n) { // Base Condition if (rx - lx == 1) { if (st[x] == k) return lx; return n; } // Split into two halves let m = parseInt((lx + rx) / 2, 10); // Check if kth one is in left subtree // or right subtree of current node if (st[x * 2 + 1] >= k) return getans(x * 2 + 1, lx, m, k, n); else return getans(x * 2 + 2, m, rx, k - st[x * 2 + 1], n); } // Function to generate the original // permutation function getPermutation(inv, n) { // Build segment tree build(0, 0, n); // Stores the original permutation let ans = []; for (let i = n - 1; i >= 0; i--) { // Find kth one let temp = getans(0, 0, n, st[0] - inv[i], n); // Answer for arr[i] ans.push(temp + 1); // Setting found value back to 0 update(Math.max(0, temp), 0, 0, n); } // Print the permutation for (let i = n - 1; i >= 0; i--) document.write(ans[i] + " " ); return ; } // Driver code // Given array let inv = [ 0, 1, 1, 0, 3 ]; // Length of the given array let N = inv.length; // Function Call getPermutation(inv, N); // This code is contributed by suresh07 </script> |
4 1 3 5 2
Time Complexity: O(N*log N)
Auxiliary Space: O(N)
Related Topic: Segment Tree
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!