Find a permutation of N natural numbers with K inversions

• Last Updated : 01 Nov, 2021

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++

 // C++ program of the above approach #include using namespace std;   // Function to fint 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 occured                 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

 // Java program for the above approach import java.io.*;   class GFG {     // Function to fint 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 occured                 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

Python3

 # python program of the above approach   # Function to fint 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 occured                 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



C#

 // C# program for the above approach using System;   public class GFG {     // Function to fint 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 occured                 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

Output

5 1 2 3 4

Time complexity: O(N)
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up
Recommended Articles
Page :