K Inverse Pairs Array - LeetCode
题目:
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.
又是一道动态规划的题目。
这道题比我做的前两道动态规划难一点,但是状态转移方程还是比较容易想到的。
用a[k][n]
表示n个数能够组成具有k对逆序数的数列的个数。
比如:
a[1][2]=1 --- [2,1]
a[1][3]=2 --- [1,3,2],[2,1,3]
下面来说一下状态转移方程。
当n个数变成n+1个数时,增加的这个数是最大的数(n+1比所有其它数都大),我们可以想象成把n+1这个数插入到前n个数的排列中,对于前n个数的每一种排列,可以有n+1中插入方法,
X X X ….. X X X n+1 (插在最后)
X X X ….. X X n+1 X (插在倒数第二)
X X X ….. X n+1 X X (插在倒数第三)
….以此类推
如果插在最后,那么逆序对的数量和原来是相同的。
如果插在倒数第二,那么逆序对的数量会比原来多1。
如果插在倒数第二,那么逆序对的数量会比原来多2。
以此类推
这样就不难写出状态转移方程
a[k][n] = a[k][n-1]+a[k-1][n-1]+...+a[k+1-n][n-1]
实际写代码的时候状态转移的公式会与上面有些出入,但思路仍然是不变的,只是找到了规律,化简了一下。
a是个二维数组,这道题对a先按行求或者先按列求都是可以的,下面是按列求的代码。
class Solution {
public:
int kInversePairs(int n, int k) {
int mod = (int)pow(10, 9)+7;
vector< vector<int> > a(k + 1, vector<int>(n+1, 0));
for (int i = 0; i <= n; i++) {
a[0][i] = 1;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= k; j++) {
if (j-i >= 0) {
a[j][i] = (a[j-1][i]+a[j][i-1])%mod;
a[j][i] = (a[j][i]-a[j-i][i-1]+mod)%mod;
}
else
a[j][i] = (a[j-1][i]+a[j][i-1])%mod;
}
}
return a[k][n];
}
};
mod是个坑点,看了答案才知道a[j][i] = (a[j][i]-a[j-i][i-1]+mod)%mod
这里要加上mod在取余数,否则有可能变成负数。