Generate lexicographically smallest Permutation of 1 to N where elements follow given relation
Last Updated :
22 Feb, 2023
Given an integer N and an array arr[] of M pairs of type (Ai, Bi), the task is to generate the lexicographically smallest possible permutation of 1 to N such that every Ai, occurs before every Bi.
Examples:
Input: N = 4, arr[] = { {2, 1}, {3, 4}, {2, 4} }
Output: 2 1 3 4
Explanation: The following five permutations P satisfy the condition:
(2, 1, 3, 4), (2, 3, 1, 4), (2, 3, 4, 1), (3, 2, 1, 4), (3, 2, 4, 1).
The lexicographically smallest among them is (2, 1, 3, 4).
Input: N = 2, arr[] = { {2, 1} }
Output: 2 1
Approach: The problem can be solved using the concept of Graph based on the following idea:
Consider a N vertex graph where there is an directed edge from A to B if A occurs before B in the permutation.
- So the target is to find a ordering such that any vertex occurs in the permutation after all its predecessors (the vertices which have edges directed to this one) have occurred in the permutation.
- While doing so, move from the least value to the maximum possible value for getting the lexicographically smallest permutation.
This can be done with the help of topological sorting.
- The topological sort will start from the vertices having indegree 0 and in sequence of smaller to greater value.
- After the topological sorting is over, if any vertex is still not included in the permutation, then no such permutation is possible.
Follow the below steps to solve the problem:
- Initialize one vector (say ans) to store the resulting permutation.
- Visit the M pairs and create directed edges from the first value of arr[i] to the second value of arr[i]. Also, increase the indegree of the second value of arr[i] by 1.
- Now find all the elements with indegree 0, push them in the resultant permutation in increasing order and start the topological sort.
- Add any vertex to the permutation when its indegree becomes 0.
- Maintain the lexicographic ordering while doing so, i.e. move from the lower value to the higher value.
- Take the help of min heap to perform the topological sorting:
- Initially keep the vertices with indegree 0 in the heap.
- Then pop the least value vertex, append it to the ans, remove all its edges and decrease the indegree by 1 of all the vertices connected to it.
- If the indegree of any vertex becomes 0 in this process, push that into the heap.
- Return ans as the final required permutation.
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
vector< int > Calculate( int n, int m,
vector<pair< int , int > > arr)
{
vector< int > ans;
vector< int > indegree(n);
vector<vector< int > > out(n);
for ( int i = 0; i < m; i++) {
int a = arr[i].first;
int b = arr[i].second;
a--;
b--;
indegree[b] = indegree[b] + 1;
out[a].push_back(b);
}
priority_queue< int , vector< int >,
greater< int > >
heap;
for ( int i = 0; i < n; ++i) {
if (indegree[i] == 0) {
heap.push(i);
}
}
while (!heap.empty()) {
int i = heap.top();
heap.pop();
ans.push_back(i + 1);
for ( int j : out[i]) {
indegree[j] -= 1;
if (indegree[j] == 0) {
heap.push(j);
}
}
}
if (ans.size() != n) {
ans.clear();
ans.push_back(-1);
}
return ans;
}
int main()
{
int N = 4, M = 3;
vector<pair< int , int > > arr
= { { 2, 1 }, { 3, 4 }, { 2, 4 } };
vector< int > res = Calculate(N, M, arr);
for ( int x : res)
cout << x << " " ;
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
public static ArrayList<Integer> Calculate( int n, int m,
int arr[][])
{
ArrayList<Integer> ans = new ArrayList<Integer>();
int indegree[] = new int [n];
ArrayList<ArrayList<Integer> > out
= new ArrayList<ArrayList<Integer> >(n);
for ( int i = 0 ; i < n; i++) {
out.add( new ArrayList<Integer>());
}
for ( int i = 0 ; i < m; i++) {
int a = arr[i][ 0 ];
int b = arr[i][ 1 ];
a--;
b--;
indegree[b] = indegree[b] + 1 ;
out.get(a).add(b);
}
PriorityQueue<Integer> heap = new PriorityQueue<>();
for ( int i = 0 ; i < n; ++i) {
if (indegree[i] == 0 ) {
heap.add(i);
}
}
while (!heap.isEmpty()) {
int i = heap.peek();
heap.poll();
ans.add(i + 1 );
for (Integer j : out.get(i)) {
indegree[j] -= 1 ;
if (indegree[j] == 0 ) {
heap.add(j);
}
}
}
if (ans.size() != n) {
ans.clear();
ans.add(- 1 );
}
return ans;
}
public static void main(String[] args)
{
int N = 4 , M = 3 ;
int arr[][] = { { 2 , 1 }, { 3 , 4 }, { 2 , 4 } };
ArrayList<Integer> res = Calculate(N, M, arr);
for (Integer x : res)
System.out.print(x + " " );
}
}
|
Python3
def Calculate(n, m, arr):
ans = []
indegree = [ 0 ] * n
out = [[] for i in range (n)]
for i in range (m):
a = arr[i][ 0 ]
b = arr[i][ 1 ]
a - = 1
b - = 1
indegree[b] + = 1
out[a].append(b)
heap = []
for i in range (n):
if indegree[i] = = 0 :
heap.append(i)
while heap:
i = heap.pop( 0 )
ans.append(i + 1 )
for j in out[i]:
indegree[j] - = 1
if indegree[j] = = 0 :
heap.append(j)
if len (ans) ! = n:
ans = [ - 1 ]
return ans
if __name__ = = '__main__' :
n = 4
m = 3
arr = [[ 2 , 1 ], [ 3 , 4 ], [ 2 , 4 ]]
res = Calculate(n, m, arr)
print (res)
|
C#
using System;
using System.Collections.Generic;
class GFG {
static List< int > Calculate( int n, int m, int [, ] arr)
{
List< int > ans = new List< int >();
int [] indegree = new int [n];
List<List< int > > Out = new List<List< int > >();
for ( var i = 0; i < n; i++)
Out.Add( new List< int >());
for ( var i = 0; i < m; i++) {
var a = arr[i, 0];
var b = arr[i, 1];
a -= 1;
b -= 1;
indegree[b] += 1;
Out[a].Add(b);
}
List< int > heap = new List< int >();
for ( var i = 0; i < n; i++) {
if (indegree[i] == 0) {
heap.Add(i);
}
}
while (heap.Count > 0) {
heap.Sort();
var i = heap[0];
heap.RemoveAt(0);
ans.Add(i + 1);
for ( var k = 0; k < Out[i].Count; k++) {
var j = Out[i][k];
indegree[j] -= 1;
if (indegree[j] == 0)
heap.Add(j);
}
}
if (ans.Count != n) {
ans.Clear();
ans.Add(-1);
}
return ans;
}
public static void Main( string [] args)
{
var n = 4;
var m = 3;
int [, ] arr = { { 2, 1 }, { 3, 4 }, { 2, 4 } };
var res = Calculate(n, m, arr);
foreach ( var i in res) Console.Write(i + " " );
}
}
|
Javascript
function Calculate(n, m, arr)
{
var ans = [];
var indegree = new Array(n).fill(0);
var out = [];
for ( var i = 0; i < n; i++)
out.push([ ]);
for ( var i = 0; i < m; i++)
{
var a = arr[i][0];
var b = arr[i][1];
a -= 1;
b -= 1;
indegree[b] += 1;
out[a].push(b);
}
var heap = [];
for ( var i = 0; i < n; i++)
{
if (indegree[i] == 0)
{
heap.push(i);
}
}
while (heap.length > 0)
{
var i = heap.shift();
ans.push(i + 1);
for ( var k = 0; k < out[i].length; k++)
{
var j = out[i][k];
indegree[j] -= 1;
if (indegree[j] == 0)
heap.push(j);
}
}
if (ans.length != n)
ans = [-1];
return ans;
}
var n = 4;
var m = 3;
var arr = [[2, 1], [3, 4], [2, 4]];
var res = Calculate(n, m, arr);
console.log(res);
|
Time Complexity: O(N+M*log(M)) where N is the number of vertices and M is the number of edges in the directed graph.
Auxiliary Space: O(N+M)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...