给定两个整数N和K ,任务是计算刚好有K 次反转的前N 个自然数的排列数。由于计数可能非常大,将其打印为模10 9 + 7 。
An inversion is defined as a pair a[i], a[j] such that a[i] > a[j] and i < j.
例子:
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
朴素的方法:请参阅上一篇文章,了解解决问题的最简单的方法。
时间复杂度: O(N*N!)
辅助空间: O(1)
Dynamic Programming using Top-Down Approach:有关自顶向下方法,请参阅本文的前一篇文章。
时间复杂度: O(N*K 2 )
辅助空间: O(N*K)
使用自底向上方法进行动态规划:
插图:
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.
请按照以下步骤解决问题:
- 创建一个辅助数组dp[2][K + 1] ,其中dp[N][K]存储(N – 1) 个数字的所有排列,其中K = (max(K – (N – 1), 0) to K)反转,通过将第N个数字与它们相加一次。
- 使用dp[i % 2][K]将在两行之间交换迭代并取j = Max(K – (N – 1), 0) 。所以dp[N[K] = dp[N-1][j] + dp[N-1][j+1] + …. + dp[N – 1][K] 。
- 为了计算dp[N][K]不需要做这个额外的K迭代,因为它可以在 O(1) 中从dp[N][K – 1] 获得。所以递推关系由下式给出:
- dp[N][K] = dp[N][K – 1] + dp[N – 1][K] – dp[N – 1][max(K – (N – 1), 0) – 1]
- 分别使用变量i和j在N和K 上迭代两个嵌套循环,并根据上述递归关系更新每个 dp 状态。
- 打印上述步骤后dp[N%2][K]的值作为结果。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
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
2
时间复杂度: O(N * K)
辅助空间: O(K)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。