Given two integers N and K, the task is to find a permutation of first N natural numbers with exactly K inversions.
Examples :
Input: N = 5, K = 4
Output: 5 1 2 3 4
Explanation: In the above permutation P, the pairs (i, j) such that i < j and P[i] > P[j] are (0, 1), (0, 2), (0, 3), and (0, 4). Hence, the number of inversions in the above permutation is 4 which is the required value.Input: N = 3, K = 4
Output: -1
Explanation: No possible permutation of first 3 natural numbers has exactly 4 inversions.
Approach: The given problem can be solved by a Greedy Approach. It can be observed that if the maximum element of an array of N elements is assigned at ith position, it will contribute (N – i) inversions. Using this observation, follow the below steps to solve the given problem:
- Check for the condition whether K > the maximum number of possible inversions (i.e, N*(N-1)/2). If true, return -1.
- Create a variable curr, which keeps track of the current maximum element of the array. Initially curr = N.
- Create an array p[], which keeps track of the current permutation.
- Iterate using a variable i in the range [1, N], and if K > (curr – i), assign curr to the current position of the array and subtract (curr – i) from K. Also, decrement the value of curr by 1.
- If K > (curr – i) is false, assign K+1 to the current index and assign the remaining integers in increasing order in the array p[].
Below is the implementation of the above approach:
// C++ program of the above approach #include <bits/stdc++.h> using namespace std;
// Function to find the permutation of // N natural numbers with k inversions void findPermutation( int n, int k)
{ // Stores the maximum number of inversions
int max_inv = (n * (n - 1)) / 2;
// If required inversions are more that max
if (k > max_inv) {
cout << "-1" ;
return ;
}
// Stores the final permutation
int p[n + 1];
// Keep track of the current max element
// in the permutation
int curr = n;
int i = 1;
// Loop to iterate through the array
for (i = 1; i <= n; i++) {
// Set current element as ith element
// in order to increase n-i inversions
// in the given permutation
if (k >= n - i) {
p[i] = curr;
curr--;
k -= (n - i);
}
// Otherwise set (k+1) element at ith index
// ans assign the remaining indices
else {
// If the remaining inversion count is
// greater than 0
if (k == 0) {
i--;
}
else {
p[i] = k + 1;
}
// Set the next index as 1
p[i + 1] = 1;
// Loop to assign the remaining indices
for ( int j = i + 2; j <= n; j++) {
p[j] = p[j - 1] + 1;
// If current element already occurred
if (p[i] == p[j]) {
p[j]++;
}
}
break ;
}
}
// Print Answer
for ( int j = 1; j <= n; j++) {
cout << p[j] << " " ;
}
} // Driver code int main()
{ int n = 5;
int k = 4;
findPermutation(n, k);
return 0;
} |
// Java program for the above approach import java.io.*;
class GFG {
// Function to find the permutation of // N natural numbers with k inversions static void findPermutation( int n, int k)
{ // Stores the maximum number of inversions
int max_inv = (n * (n - 1 )) / 2 ;
// If required inversions are more that max
if (k > max_inv) {
System.out.println( "-1" );
return ;
}
// Stores the final permutation
int [] p = new int [n+ 1 ];
// Keep track of the current max element
// in the permutation
int curr = n;
int i = 1 ;
// Loop to iterate through the array
for (i = 1 ; i <= n; i++) {
// Set current element as ith element
// in order to increase n-i inversions
// in the given permutation
if (k >= n - i) {
p[i] = curr;
curr--;
k -= (n - i);
}
// Otherwise set (k+1) element at ith index
// ans assign the remaining indices
else {
// If the remaining inversion count is
// greater than 0
if (k == 0 ) {
i--;
}
else {
p[i] = k + 1 ;
}
// Set the next index as 1
p[i + 1 ] = 1 ;
// Loop to assign the remaining indices
for ( int j = i + 2 ; j <= n; j++) {
p[j] = p[j - 1 ] + 1 ;
// If current element already occurred
if (p[i] == p[j]) {
p[j]++;
}
}
break ;
}
}
// Print Answer
for ( int j = 1 ; j <= n; j++) {
System.out.print(p[j] + " " );
}
} // Driver code public static void main (String[] args) {
int n = 5 ;
int k = 4 ;
findPermutation(n, k);
}
} // This code is contributed by Potta Lokesh |
# python program of the above approach # Function to find the permutation of # N natural numbers with k inversions def findPermutation(n, k):
# Stores the maximum number of inversions
max_inv = (n * (n - 1 )) / 2
# If required inversions are more that max
if (k > max_inv):
print ( "-1" )
return
# Stores the final permutation
p = [ 0 for _ in range (n + 1 )]
# Keep track of the current max element
# in the permutation
curr = n
i = 1
# Loop to iterate through the array
for i in range ( 1 , n + 1 ):
# Set current element as ith element
# in order to increase n-i inversions
# in the given permutation
if (k > = n - i):
p[i] = curr
curr - = 1
k - = (n - i)
# Otherwise set (k+1) element at ith index
# ans assign the remaining indices
else :
# If the remaining inversion count is
# greater than 0
if (k = = 0 ):
i - = 1
else :
p[i] = k + 1
# Set the next index as 1
p[i + 1 ] = 1
# Loop to assign the remaining indices
for j in range (i + 2 , n + 1 ):
p[j] = p[j - 1 ] + 1
# If current element already occurred
if (p[i] = = p[j]):
p[j] + = 1
break
# Print Answer
for j in range ( 1 , n + 1 ):
print (p[j], end = " " )
# Driver code if __name__ = = "__main__" :
n = 5
k = 4
findPermutation(n, k)
# This code is contributed by rakeshsahni |
<script> // JavaScript program of the above approach
// Function to find the permutation of
// N natural numbers with k inversions
const findPermutation = (n, k) => {
// Stores the maximum number of inversions
let max_inv = (n * (n - 1)) / 2;
// If required inversions are more that max
if (k > max_inv) {
document.write( "-1" );
return ;
}
// Stores the final permutation
let p = new Array(n + 1).fill(0);
// Keep track of the current max element
// in the permutation
let curr = n;
let i = 1;
// Loop to iterate through the array
for (i = 1; i <= n; i++) {
// Set current element as ith element
// in order to increase n-i inversions
// in the given permutation
if (k >= n - i) {
p[i] = curr;
curr--;
k -= (n - i);
}
// Otherwise set (k+1) element at ith index
// ans assign the remaining indices
else {
// If the remaining inversion count is
// greater than 0
if (k == 0) {
i--;
}
else {
p[i] = k + 1;
}
// Set the next index as 1
p[i + 1] = 1;
// Loop to assign the remaining indices
for (let j = i + 2; j <= n; j++) {
p[j] = p[j - 1] + 1;
// If current element already occurred
if (p[i] == p[j]) {
p[j]++;
}
}
break ;
}
}
// Print Answer
for (let j = 1; j <= n; j++) {
document.write(`${p[j]} `);
}
}
// Driver code
let n = 5;
let k = 4;
findPermutation(n, k);
// This code is contributed by rakeshsahni
</script> |
// C# program for the above approach using System;
public class GFG {
// Function to find the permutation of // N natural numbers with k inversions static void findPermutation( int n, int k)
{ // Stores the maximum number of inversions
int max_inv = (n * (n - 1)) / 2;
// If required inversions are more that max
if (k > max_inv) {
Console.WriteLine( "-1" );
return ;
}
// Stores the final permutation
int [] p = new int [n+1];
// Keep track of the current max element
// in the permutation
int curr = n;
int i = 1;
// Loop to iterate through the array
for (i = 1; i <= n; i++) {
// Set current element as ith element
// in order to increase n-i inversions
// in the given permutation
if (k >= n - i) {
p[i] = curr;
curr--;
k -= (n - i);
}
// Otherwise set (k+1) element at ith index
// ans assign the remaining indices
else {
// If the remaining inversion count is
// greater than 0
if (k == 0) {
i--;
}
else {
p[i] = k + 1;
}
// Set the next index as 1
p[i + 1] = 1;
// Loop to assign the remaining indices
for ( int j = i + 2; j <= n; j++) {
p[j] = p[j - 1] + 1;
// If current element already occurred
if (p[i] == p[j]) {
p[j]++;
}
}
break ;
}
}
// Print Answer
for ( int j = 1; j <= n; j++) {
Console.Write(p[j] + " " );
}
} // Driver code public static void Main ( string [] args) {
int n = 5;
int k = 4;
findPermutation(n, k);
}
} // This code is contributed by AnkThon |
5 1 2 3 4
Time complexity: O(N)
Auxiliary Space: O(N)