Skip to content
Related Articles

Related Articles

Improve Article
Save Article
Like Article

Number of permutation with K inversions | Set 2

  • Difficulty Level : Hard
  • Last Updated : 27 Jul, 2021

Given two integers N and K, the task is to count the number of permutations of the first N natural numbers having exactly K inversions. Since the count can be very large, print it modulo 109 + 7.

An inversion is defined as a pair a[i], a[j] such that a[i] > a[j] and i < j.

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.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

Examples:



Input: N = 3, K = 2
Output: 2
Explanation:
All Permutations for N = 3 are 321, 231, 213, 312, 132, 123.
Out of which only 231 and 312 have 2 inversions as:

  • 231: 2 > 1 & 3 > 1
  • 312: 3 > 1 & 3 > 2.

Therefore, both are satisfying the condition of having exactly K inversions.

Input: N = 5, K = 5
Output: 22

 

Naive Approach: Refer to the previous post for the simplest possible approach to solve the problem. 
Time Complexity: O(N*N!)
Auxiliary Space: O(1)

Dynamic Programming using Top-Down Approach: Refer to the previous post of this article for the Top-Down Approach. 
Time Complexity: O(N*K2)
Auxiliary Space: O(N*K)

Dynamic Programming using Bottom-Up Approach:

Illustration:

For Example: N = 4, K = 2

N – 1 = 3, K0 = 0 …   123           =>  1423
N – 1 = 3, K1 = 1 …   213, 132   =>  2143, 1342
N – 1 = 3, K2 = 2 …   231, 312   =>  2314, 3124
So the answer is 5.

The maximum value is taken between (K – N + 1) and 0 as K inversions cannot be obtained if the number of inversions in permutation of (N – 1) numbers is less than K – (N – 1) as at most (N – 1) new inversions can be obtained by adding Nth number at the beginning.

Follow the steps below to solve the problem:

  • Create an auxiliary array dp[2][K + 1] where dp[N][K] stores all permutations of (N – 1) numbers with K = (max(K – (N – 1), 0) to K) inversions, by adding Nth number with them only once.
  • Using dp[i % 2][K] will interchange iteration between two rows and take j = Max(K – (N – 1), 0). So dp[N[K] = dp[N-1][j] + dp[N-1][j+1] + …. + dp[N – 1][K].
  • For calculating dp[N][K] there is no need to do this extra K iteration as it can be obtained in O(1) from dp[N][K – 1]. So the recurrence relation is given by:
    • dp[N][K] = dp[N][K – 1] + dp[N – 1][K] – dp[N – 1][max(K – (N – 1), 0) – 1]
  • Iterate two nested loops using the variable i and j over N and K respectively and update each dp states as per the above recurrence relation.
  • Print the value of dp[N%2][K] after the above steps as the result.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
  
#include <bits/stdc++.h>
using namespace std;
  
// Function to count permutations with
// K inversions
int numberOfPermWithKInversion(
    int N, int K)
{
    // Store number of permutations
    // with K inversions
    int dp[2][K + 1];
  
    int mod = 1000000007;
  
    for (int i = 1; i <= N; i++) {
        for (int j = 0; j <= K; j++) {
  
            // If N = 1 only 1 permutation
            // with no inversion
            if (i == 1)
                dp[i % 2][j] = (j == 0);
  
            // For K = 0 only 1 permutation
            // with no inversion
            else if (j == 0)
                dp[i % 2][j] = 1;
  
            // Otherwise Update each dp
            // state as per the reccurrance
            // relation formed
            else
                dp[i % 2][j]
                    = (dp[i % 2][j - 1] % mod
                       + (dp[1 - i % 2][j]
                          - ((max(j - (i - 1), 0) == 0)
                                 ? 0
                                 : dp[1 - i % 2]
                                     [max(j - (i - 1), 0)
                                      - 1])
                          + mod)
                             % mod)
                      % mod;
            ;
        }
    }
  
    // Print final count
    cout << dp[N % 2][K];
}
  
// Driver Code
int main()
{
    // Given N and K
    int N = 3, K = 2;
  
    // Function Call
    numberOfPermWithKInversion(N, K);
  
    return 0;
}

Java




// Java program for the above approach
import java.io.*;
  
class GFG{
  
// Function to count permutations with
// K inversions
static void numberOfPermWithKInversion(int N, int K)
{
      
    // Store number of permutations
    // with K inversions
    int[][] dp = new int[2][K + 1];
  
    int mod = 1000000007;
  
    for(int i = 1; i <= N; i++) 
    {
        for(int j = 0; j <= K; j++) 
        {
              
            // If N = 1 only 1 permutation
            // with no inversion
            if (i == 1)
            {
                dp[i % 2][j] = (j == 0) ? 1 : 0;
            }
  
            // For K = 0 only 1 permutation
            // with no inversion
            else if (j == 0)
                dp[i % 2][j] = 1;
  
            // Otherwise Update each dp
            // state as per the reccurrance
            // relation formed
            else
                {
                 int maxm = Math.max(j - (i - 1));
             dp[i % 2][j] = (dp[i % 2][j - 1] % mod +
                               (dp[1 - i % 2][j] - 
                               ((Math.max(j - (i - 1), 0) == 0) ?
                                   0 : dp[1 - i % 2][maxm, 0) - 1]) +
                                         mod) % mod) % mod;
}
        }
    }
      
    // Print final count
    System.out.println (dp[N % 2][K]);
}
  
// Driver Code
public static void main(String[] args)
{
      
    // Given N and K
    int N = 3, K = 2;
  
    // Function Call
    numberOfPermWithKInversion(N, K);
}
}
  
// This code is contributed by akhilsaini

Python3




# Python3 program for the above approach
  
# Function to count permutations with
# K inversions
def numberOfPermWithKInversion(N, K):
      
    # Store number of permutations
    # with K inversions
    dp = [[0] * (K + 1)] * 2
  
    mod = 1000000007
  
    for i in range(1, N + 1):
        for j in range(0, K + 1):
              
            # If N = 1 only 1 permutation
            # with no inversion
            if (i == 1):
                dp[i % 2][j] = 1 if (j == 0) else 0
  
            # For K = 0 only 1 permutation
            # with no inversion
            elif (j == 0):
                dp[i % 2][j] = 1
  
            # Otherwise Update each dp
            # state as per the reccurrance
            # relation formed
            else:
                var = (0 if (max(j - (i - 1), 0) == 0)
                         else dp[1 - i % 2][max(j - (i - 1), 0) - 1])
                dp[i % 2][j] = ((dp[i % 2][j - 1] % mod +
                                (dp[1 - i % 2][j] -
                                (var) + mod) % mod) % mod)
  
    # Print final count
    print(dp[N % 2][K])
  
# Driver Code
if __name__ == '__main__':
      
    # Given N and K
    N = 3
    K = 2
  
    # Function Call
    numberOfPermWithKInversion(N, K)
  
# This code is contributed by akhilsaini

C#




// C# program for the above approach
using System;
  
class GFG{
  
// Function to count permutations with
// K inversions
static void numberOfPermWithKInversion(int N, int K)
{
      
    // Store number of permutations
    // with K inversions
    int[,] dp = new int[2, K + 1];
  
    int mod = 1000000007;
  
    for(int i = 1; i <= N; i++)
    {
        for(int j = 0; j <= K; j++) 
        {
              
            // If N = 1 only 1 permutation
            // with no inversion
            if (i == 1)
            {
                dp[i % 2, j] = (j == 0) ? 1 : 0;
            }
  
            // For K = 0 only 1 permutation
            // with no inversion
            else if (j == 0)
                dp[i % 2, j] = 1;
  
            // Otherwise Update each dp
            // state as per the reccurrance
            // relation formed
            else
                dp[i % 2, j] = (dp[i % 2, j - 1] % mod + 
                               (dp[1 - i % 2, j] - 
                               ((Math.Max(j - (i - 1), 0) == 0) ?
                                   0 : dp[1 - i % 2, Math.Max(
                                          j - (i - 1), 0) - 1]) +
                                              mod) % mod) % mod;
        }
    }
  
    // Print final count
    Console.WriteLine(dp[N % 2, K]);
}
  
// Driver Code
public static void Main()
{
  
    // Given N and K
    int N = 3, K = 2;
  
    // Function Call
    numberOfPermWithKInversion(N, K);
}
}
  
// This code is contributed by akhilsaini

Javascript




<script>
  
// Javascript program to implement
// the above approach
  
// Function to count permutations with
// K inversions
function numberOfPermWithKInversion(N, K)
{
        
    // Store number of permutations
    // with K inversions
    let dp = new Array(2);
    // Loop to create 2D array using 1D array
    for (var i = 0; i < dp.length; i++) 
    {
    dp[i] = new Array(2);
    }
    
    let mod = 1000000007;
    
    for(let i = 1; i <= N; i++) 
    {
        for(let j = 0; j <= K; j++) 
        {
                
            // If N = 1 only 1 permutation
            // with no inversion
            if (i == 1)
            {
                dp[i % 2][j] = (j == 0) ? 1 : 0;
            }
    
            // For K = 0 only 1 permutation
            // with no inversion
            else if (j == 0)
                dp[i % 2][j] = 1;
    
            // Otherwise Update each dp
            // state as per the reccurrance
            // relation formed
            else
                dp[i % 2][j] = (dp[i % 2][j - 1] % mod +
                 (dp[1 - i % 2][j] - 
                 ((Math.max(j - (i - 1), 0) == 0) ?
                   0 : dp[1 - i % 2][Math.max(j - 
                          (i - 1), 0) - 1]) +
                             mod) % mod) % mod;
        }
    }
        
    // Print final count
    document.write(dp[N % 2][K]);
}
      
    // Driver Code
       
           // Given N and K
    let N = 3, K = 2;
    
    // Function Call
    numberOfPermWithKInversion(N, K);
    
</script>

 
 

Output: 
2

 

 

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

 




My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!