题目:
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].
代码:
方法一——超时,直接的思路:
class Solution {
public:
int kInversePairs(int n, int k) {
vector<vector<int>> v(n + 1, vector<int>(k+1, 0));
v[1][0] = 1;
for (int i = 2; i <= n; i++) {
for (int j = 0; j <= k; j++) {
int n = j;
while (n>=0&&n >= j-i+1) {
v[i][j]=(v[i][j]+v[i-1][n])%1000000007;
n--;
}
}
}
return v[n][k];
}
};
方法二——进行时间优化之后:
class Solution {
public:
int kInversePairs(int n, int k) {
int M = 1000000007;
vector<vector<int>> dp(n + 1, vector<int>(k + 1, 0));
dp[0][0] = 1;
for (int i = 1; i <= n; ++i) {
dp[i][0] = 1;
for (int j = 1; j <= k; ++j) {
dp[i][j] = (dp[i - 1][j] + dp[i][j - 1]) % M;
if (j >= i) {
dp[i][j] = (dp[i][j] - dp[i - 1][j - i] + M) % M;
}
}
}
return dp[n][k];
}
};
思路:使用一些小trick——
dp[n][k] = dp[n - 1][k] + dp[n - 1][k-1] + ... + dp[n - 1][k - n + 1]
我们可以用k+1代替k,得到:
dp[n][k+1] = dp[n - 1][k+1] + dp[n - 1][k] + ... + dp[n - 1][k + 1 - n + 1]
用第二个等式减去第一个等式可以得到:
dp[n][k+1] = dp[n][k] + dp[n - 1][k+1] - dp[n - 1][k - n + 1]
将k+1换回成k,可以得到:
dp[n][k] = dp[n][k-1] + dp[n - 1][k] - dp[n - 1][k - n]
我们可以发现当k>=n的时候,最后一项的数组坐标才能为非负数,从而最后一项才有值,所以我们再更新的时候只需要判断一下k和n的关系,如果k>=n的话,就要减去最后一项,这种递推式算起来更高效,减少了一个循环