Number of permutation with K inversions

来源:互联网 发布:软件开发 工作经验 编辑:程序博客网 时间:2024/06/06 13:07

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 permutation of first N number have exactly K inversion.

给定一个数组,inversion被定义为a [i],a [j],使得[i]> a [j]和i < j。 我们给出两个数字N和k,我们需要计算出 N 个数的排列有多少个正好是K个inversion。

例如:
输入 : N = 3, K = 1
输出 : 2
Explanation :
全部的可能情况:
123, 132, 213, 231, 312, 321
符合条件的情况 : 132 and 213

输入 : N = 4, K = 2

输出 : 2

解法的伪代码如下:

If N is 0, Count(0, K) = 0If 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(N1, K - 1) +               Count(N1, K2) +               .... +               Count(N1, 0)

其解法思想如下:

如果我们有N个数并希望有K个inversion,并且假设(N-1)个数的所有inversion写在某个地方,那么新数(第N个数,即最大的数)需要被置于(N-1)个数的所有inversion中,在我们的答案中应该加上那些inversion计数变为K后的组合。

简单的说就是将第N个数插入在前N-1个数的所有组合中,将inversion=k的情况相加。
下面给出了各个情况的示意图:
1. 前n-1个已经组成了inversions=k,则第n个只需要插入在最后。
image
2. 前n-1个已经组成了inversions=k-1,则第n个需要往前插 1 位,让inversions=k。
image
3. 前n-1个已经组成了inversions=k-2,则第n个需要往前插 2 位,让inversions=k。
image



依次类推:
image

实现代码如下(c++):

// C++ program to find number of permutation with// K inversion using Memoization#include <bits/stdc++.h>using namespace std;// Limit on N and Kconst int M = 100// 2D array memo for stopping solving same problem// againint memo[M][M];// method recursively calculates permutation with// K inversionint numberOfPermWithKInversion(int N, int K){    //  base cases    if (N == 0)        return 0;    if (K == 0)        return 1;    //  if already solved then return result directly    if (memo[N][K] != 0)        return memo[N][K];    // calling recursively all subproblem of    // permutation size N - 1    int sum = 0;    for (int i = 0; i <= K; i++)    {        // Call recursively only if total inversion        // to be made are less than size        if (i <= N - 1)            sum += numberOfPermWithKInversion(N-1, K-i);    }    //  store result into memo    memo[N][K] = sum;    return sum;}//  Driver code to test above methodsint main(){    int N = 4;    int K = 2;    cout << numberOfPermWithKInversion(N, K);    return 0;}

Output:

5