K Inverse Pairs Array - LeetCode

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在取余数,否则有可能变成负数。

猜你喜欢

转载自blog.csdn.net/sgafpzys/article/details/78573942