629. K Inverse Pairs Array
Given two integers n
and k
, find how many different arrays consist of numbers from 1
to n
such that there are exactly k
inverse pairs.
We define an inverse pair as following: For ith
and jth
element in the array, if i
< j
and a[i]
> a[j]
then it's an inverse pair; Otherwise, it's not.
Since the answer may be very large, the answer should be modulo 109 + 7.
Example 1:
Input: n = 3, k = 0 Output: 1 Explanation: Only the array [1,2,3] which consists of numbers from 1 to 3 has exactly 0 inverse pair.
Example 2:
Input: n = 3, k = 1 Output: 2 Explanation: The array [1,3,2] and [2,1,3] have exactly 1 inverse pair.
Note:
- The integer
n
is in the range [1, 1000] andk
is in the range [0, 1000].
Approach #1: DP. [C++]
class Solution { public: int kInversePairs(int n, int k) { vector<vector<int>> dp(n+1, vector<int>(k+1, 0)); dp[0][0] = 1; for (int i = 1; i <= n; ++i) { for (int j = 0; j < i; ++j) { for (int m = 0; m <= k; ++m) { if (m - j >= 0 && m - j <= k) { dp[i][m] = (dp[i][m] + dp[i-1][m-j]) % mod; } } } } return dp[n][k]; } private: const int mod = pow(10, 9) + 7; };
Analysis:
For example, if we have some permutation of 1 ..... 4
5 * * * * creates 4 new inverse pairs
* 5 * * * creates 3 new inverse pairs
* * 5 * * creates 2 new inverse pairs
* * * 5 * creates 1 new inverse pairs
* * * * 5 creates 0 new inverse pairs
We can use this formula to solve this problem
dp[i][j] : represent the number of permutations of (1 ... n) with k inverse pairs.
dp[i][j] = dp[i-1][j] + dp[i-1][j-1] + dp[i-1][j-2] + ..... + dp[i-1][j-i+1]
Approach #2 Optimization. [Java]
class Solution { public int kInversePairs(int n, int k) { int mod = 1000000007; if (k > n*(n-1)/2 || k < 0) return 0; if (k == 0 || k == n*(n-1)/2) return 1; long[][] dp = new long[n+1][k+1]; dp[2][0] = 1; dp[2][1] = 1; for (int i = 3; i <= n; i++) { dp[i][0] = 1; for (int j = 1; j <= Math.min(k, i*(i-1)/2); j++) { dp[i][j] = dp[i][j-1] + dp[i-1][j]; if (j >= i) dp[i][j] -= dp[i-1][j-i]; dp[i][j] = (dp[i][j] + mod) % mod; } } return (int)dp[n][k]; } }
Analysis:
Look back to the above formula.
Let's consider this example
if i = 5:
We can find the rules about above formula.
if j < i, we can compute dp[i][j] = dp[i][j-1] + dp[i-1][j]
So how about j >= i
We know if we add number i into permutation(0 .. i-1), i can create 0 ~ i-1 inverse pair.
If j >= i, we still use dp[i][j] = dp[i][j-1] + dp[i-1][j].
We must minus dp[i][j-1]. (In fact it minus dp[i-1][j-1], because every j >= i in dp array, it minus dp[i-1][j-i] individually)
For example, if i = 5
Reference:
https://leetcode.com/problems/k-inverse-pairs-array/discuss/104815/Java-DP-O(nk)-solution
https://leetcode.com/problems/k-inverse-pairs-array/discuss/104825/Shared-my-C%2B%2B-O(n-*-k)-solution-with-explanation