Number of permutation with K inversions
Last Updated :
13 Mar, 2023
Given an array, an inversion is defined as a pair a[i], a[j] such that a[i] > a[j] and i < j. We are given two numbers N and k, we need to tell how many permutations of the first N number have exactly K inversion.
Examples:
Input : N = 3, K = 1
Output : 2
Explanation :
Total Permutation of first N number,
123, 132, 213, 231, 312, 321
Permutation with 1 inversion : 132 and 213
Input : N = 4, K = 2
Output : 5
A Naïve way to solve this problem is noting down all permutations then checking the count of inversion in them but iterating through permutation itself will take O(N!) time, which is too large.
We can solve this problem using a dynamic programming approach. Below is the recursive formula.
If N is 0, Count(0, K) = 0
If K is 0, Count(N, 0) = 1 (Only sorted array)
In general case,
If we have N number and require K inversion,
Count(N, K) = Count(N - 1, K) +
Count(N – 1, K - 1) +
Count(N – 1, K – 2) +
.... +
Count(N – 1, 0)
How does the above recursive formula work?
If we have N number and want to have K permutation and suppose all permutation of (N – 1) number are written somewhere, the new number (Nth number and largest) need to be placed in all permutation of (N – 1) number and those whose inversion count becomes K after adding this number should be added in our answer. Now take those sets of permutation of (N – 1) number which has let (K – 3) inversion, now we can place this new largest number at position 3 from last, then inversion count will be K, so count(N – 1, K – 3) should be added to our answer, the same argument can be given for another inversion also and we will reach to above recursion as the final answer.
The below code is written following the above recursion in a memorization way.
C++
#include <bits/stdc++.h>
using namespace std;
const int M = 100;
int memo[M][M];
int numberOfPermWithKInversion( int N, int K)
{
if (N == 0)
return 0;
if (K == 0)
return 1;
if (memo[N][K] != 0)
return memo[N][K];
int sum = 0;
for ( int i = 0; i <= K; i++)
{
if (i <= N - 1)
sum += numberOfPermWithKInversion(N - 1,
K - i);
}
memo[N][K] = sum;
return sum;
}
int main()
{
int N = 4;
int K = 2;
cout << numberOfPermWithKInversion(N, K);
return 0;
}
|
Java
import java.io.*;
class GFG {
static int M = 100 ;
static int memo[][] = new int [M][M];
static int numberOfPermWithKInversion( int N, int K)
{
if (N == 0 )
return 0 ;
if (K == 0 )
return 1 ;
if (memo[N][K] != 0 )
return memo[N][K];
int sum = 0 ;
for ( int i = 0 ; i <= K; i++) {
if (i <= N - 1 )
sum += numberOfPermWithKInversion(N - 1 ,
K - i);
}
memo[N][K] = sum;
return sum;
}
public static void main(String[] args)
{
int N = 4 ;
int K = 2 ;
System.out.println(numberOfPermWithKInversion(N, K));
}
}
|
Python3
M = 100
memo = [[ 0 for i in range (M)] for j in range (M)]
def numberOfPermWithKInversion(N, K):
if (N = = 0 ): return 0
if (K = = 0 ): return 1
if (memo[N][K] ! = 0 ):
return memo[N][K]
sum = 0
for i in range (K + 1 ):
if (i < = N - 1 ):
sum + = numberOfPermWithKInversion(N - 1 , K - i)
memo[N][K] = sum
return sum
N = 4 ; K = 2
print (numberOfPermWithKInversion(N, K))
|
C#
using System;
class GFG
{
static int M = 100;
static int [,]memo = new int [M, M];
static int numberOfPermWithKInversion( int N,
int K)
{
if (N == 0)
return 0;
if (K == 0)
return 1;
if (memo[N, K] != 0)
return memo[N, K];
int sum = 0;
for ( int i = 0; i <= K; i++)
{
if (i <= N - 1)
sum += numberOfPermWithKInversion(N - 1,
K - i);
}
memo[N, K] = sum;
return sum;
}
static public void Main ()
{
int N = 4;
int K = 2;
Console.WriteLine(numberOfPermWithKInversion(N, K));
}
}
|
PHP
<?php
function numberOfPermWithKInversion( $N , $K )
{
$memo = array ();
if ( $N == 0)
return 0;
if ( $K == 0)
return 1;
if ( $memo [ $N ][ $K ] != 0)
return $memo [ $N ][ $K ];
$sum = 0;
for ( $i = 0; $i <= $K ; $i ++)
{
if ( $i <= $N - 1)
$sum += numberOfPermWithKInversion( $N - 1,
$K - $i );
}
$memo [ $N ][ $K ] = $sum ;
return $sum ;
}
$N = 4;
$K = 2;
echo numberOfPermWithKInversion( $N , $K );
?>
|
Javascript
<script>
let M = 100;
let memo = new Array(M);
for (let i = 0; i < M; i++)
{
memo[i] = new Array(M);
for (let j = 0; j < M; j++)
{
memo[i][j] = 0;
}
}
function numberOfPermWithKInversion(N, K)
{
if (N == 0)
return 0;
if (K == 0)
return 1;
if (memo[N][K] != 0)
return memo[N][K];
let sum = 0;
for (let i = 0; i <= K; i++)
{
if (i <= N - 1)
sum += numberOfPermWithKInversion(
N - 1, K - i);
}
memo[N][K] = sum;
return sum;
}
let N = 4;
let K = 2;
document.write(numberOfPermWithKInversion(N, K));
</script>
|
Time Complexity: O(N*N*K)
Space Complexity: O(N*K)
Optimized Approach: Using Tabulation and cumulative sum
C++
#include <bits/stdc++.h>
using namespace std;
int numberOfPermWithKInversions( int N, int K) {
vector<vector< int >> dp(N+1,vector< int >(K+1));
for ( int i = 1; i <= N; i++)
dp[i][0] = 1;
for ( int i = 1; i <= N; i++)
{
for ( int j = 1; j <= K; j++)
{
int val = dp[i-1][j];
if (j >= i)
val -= dp[i-1][j-i];
dp[i][j] = dp[i][j-1] + val;
}
}
int ans = dp[N][K];
if (K >= 1)
ans -= dp[N][K-1];
return ans;
}
int main() {
int N = 4;
int K = 2;
cout << numberOfPermWithKInversions(N,K) << "\n" ;
return 0;
}
|
Java
import java.io.*;
class GFG {
static int numberOfPermWithKInversion( int N, int K)
{
int [][] dp = new int [N + 1 ][K + 1 ];
for ( int i = 1 ; i <= N; i++)
dp[i][ 0 ] = 1 ;
for ( int i = 1 ; i <= N; i++)
{
for ( int j = 1 ; j <= K; j++)
{
int val = dp[i- 1 ][j];
if (j >= i)
val -= dp[i- 1 ][j-i];
dp[i][j] = dp[i][j- 1 ] + val;
}
}
int ans = dp[N][K];
if (K >= 1 )
ans -= dp[N][K- 1 ];
return ans;
}
public static void main (String[] args) {
int N = 4 ;
int K = 2 ;
System.out.println(numberOfPermWithKInversion(N, K));
}
}
|
Python3
def numberOfPermWithKInversions(N, K):
List1, List2 = (K + 1 , N + 1 )
dp = [[ 0 for I in range (List1)] for j in range (List2)]
for i in range ( 1 ,N + 1 ):
dp[i][ 0 ] = 1
for i in range ( 1 ,N + 1 ):
for j in range ( 1 ,K + 1 ):
val = dp[i - 1 ][j]
if j > = i:
val - = dp[i - 1 ][j - i]
dp[i][j] = dp[i][j - 1 ] + val
ans = dp[N][K]
if K > = 1 :
ans - = dp[N][K - 1 ]
return ans
if __name__ = = "__main__" :
N = 4
K = 2
print (numberOfPermWithKInversions(N, K))
|
C#
using System;
using System.Collections.Generic;
class Program {
static int numberOfPermWithKInversions( int N, int K)
{
var dp = new int [N + 1, K + 1];
for ( int i = 1; i <= N; i++)
dp[i, 0] = 1;
for ( int i = 1; i <= N; i++) {
for ( int j = 1; j <= K; j++) {
int val = dp[i - 1, j];
if (j >= i)
val -= dp[i - 1, j - i];
dp[i, j] = dp[i, j - 1] + val;
}
}
int ans = dp[N, K];
if (K >= 1)
ans -= dp[N, K - 1];
return ans;
}
static void Main( string [] args)
{
int N = 4;
int K = 2;
Console.WriteLine(
numberOfPermWithKInversions(N, K));
}
}
|
Javascript
function numberOfPermWithKInversions(N, K) {
const List1 = K + 1;
const List2 = N + 1;
const dp = Array.from(Array(List2), () => new Array(List1).fill(0));
for (let i = 1; i <= N; i++) {
dp[i][0] = 1;
}
for (let i = 1; i <= N; i++) {
for (let j = 1; j <= K; j++) {
let val = dp[i-1][j];
if (j >= i) {
val -= dp[i-1][j-i];
}
dp[i][j] = dp[i][j-1] + val;
}
}
let ans = dp[N][K];
if (K >= 1) {
ans -= dp[N][K-1];
}
return ans;
}
const N = 4;
const K = 2;
console.log(numberOfPermWithKInversions(N, K));
|
Time Complexity: O(N*K)
Space Complexity: O(N*K)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...