Skip to content
Related Articles

Related Articles

Generate original permutation from given array of inversions
  • Difficulty Level : Medium
  • Last Updated : 12 Nov, 2020

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:

  1. Build a segment tree of size N and initialize all leaf nodes with value 1.
  2. 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.
  3. Similarly, find (i + 1 – arr[i])th element in the segment tree, for each i from (N – 1) to 0.
  4. 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.
  5. Finally, print the answer array ans[] in reversed order as the original permutation.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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 Condtiion
    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;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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 Condtiion
    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

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# 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 Condtiion
    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

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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 Condtiion
    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

chevron_right


Output: 

4 1 3 5 2








 

Time Complexity: O(N*log N)
Auxiliary Space: O(N)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.

My Personal Notes arrow_drop_up
Recommended Articles
Page :