Open In App

Find a permutation of N natural numbers with K inversions

Last Updated : 29 Nov, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

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




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


Python3




# 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


Javascript




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




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


Output

5 1 2 3 4 

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



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads