629. K个逆序对数组

Difficulty: 困难

给出两个整数 nk,找出所有包含从 1n 的数字,且恰好拥有 k 个逆序对的不同的数组的个数。

逆序对的定义如下:对于数组的第i个和第 j个元素,如果满i < ja[i] > a[j],则其为一个逆序对;否则不是。

由于答案可能很大,只需要返回 答案 mod 109 + 7 的值。

示例 1:

1
2
3
4
输入: n = 3, k = 0
输出: 1
解释: 
只有数组 [1,2,3] 包含了从1到3的整数并且正好拥有 0 个逆序对。

示例 2:

1
2
3
4
输入: n = 3, k = 1
输出: 2
解释: 
数组 [1,3,2] 和 [2,1,3] 都有 1 个逆序对。

说明:

  1. n 的范围是 [1, 1000] 并且 k 的范围是 [0, 1000]。

Solution

Language: ****

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
const int MOD = 1e9 + 7;
class Solution {
public:
    int kInversePairs(int n, int k) {
        int dp[1010][1010] = {0};
        dp[0][0 ] = 1;
        for(int i=1;i<=n;i++) {
            //枚举k 的位置
            for(int j=0;j<=k;j++) {
                for(int k=0;k<= min(i-1,j) ;k++) {
                    //个数为 (j-k)
                    dp[i][j] = (dp[i][j] + dp[i-1][j-k]) % MOD;
                }
            }
        }
        return dp[n][k];
    }
};

$$ dp[i][j] = \Sigma(dp[i-1][j-k]) $$

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
const int MOD = 1e9 + 7;
class Solution {
public:
    int kInversePairs(int n, int k) {
        int dp[1010][1010] = {0};
        dp[0][0 ] = 1;
        for(int i=1;i<=n;i++) {
            //枚举k 的位置
            for(int j=0;j<=k;j++) {
               long long sum = 0;
               for(int l=j-(i-1);l<=j;++l) {
                   if(l>=0) {
                       sum += dp[i-1][l];
                   }
               }
               dp[i][j] = sum % MOD;
            }
        }
        return dp[n][k];
    }
};

解题思路

这时我们可以这样想,我现在有4位数字了,再加上一位会是什么情况

xxxx5 => 多0个逆序对 xxx5x => 多1个逆序对 xx5xx => 多2个逆序对 x5xxx => 多3个逆序对 5xxxx => 多4个逆序对 由此说明在每次添加数字的时候都是有规律可循

假设第 i 个数所在位置为 k,由于数值 i 为整个数组的最大值,因此数值 ii 与前面所有数均不形成逆序对,与后面的所有数均形成逆序对。因此与数值 i 直接相关的逆向对的数量为 (i - 1)- k,由此也得出与i 不相关的逆序对数量为 j - (i - 1 - k),而与 i 不相关的逆序对数量由 f[i - 1][x] 可得出。

作者:AC_OIer 链接:https://leetcode-cn.com/problems/k-inverse-pairs-array/solution/gong-shui-san-xie-yi-dao-xu-lie-dp-zhuan-tm01/

其他序列 DP 问题

其他「序列 DP」相关内容

考虑加练如下「序列 DP」题目 🍭🍭

题目 题解 难度 推荐指数
354. 俄罗斯套娃信封问题 LeetCode 题解链接 困难 🤩🤩🤩🤩🤩
368. 最大整除子集 LeetCode 题解链接 中等 🤩🤩🤩🤩
446. 等差数列划分 II - 子序列 LeetCode 题解链接 困难 🤩🤩🤩🤩🤩
583. 两个字符串的删除操作 LeetCode 题解链接 中等 🤩🤩🤩🤩
673. 最长递增子序列的个数 LeetCode 题解链接 中等 🤩🤩🤩🤩
740. 删除并获得点数 LeetCode 题解链接 中等 🤩🤩🤩🤩🤩
978. 最长湍流子数组 LeetCode 题解链接 中等 🤩🤩🤩
1035. 不相交的线 LeetCode 题解链接 中等 🤩🤩🤩🤩
1143. 最长公共子序列 LeetCode 题解链接 中等 🤩🤩🤩🤩
1218. 最长定差子序列 LeetCode 题解链接 中等 🤩🤩🤩🤩🤩
1473. 粉刷房子 III LeetCode 题解链接 困难 🤩🤩🤩🤩
1713. 得到子序列的最少操作次数 LeetCode 题解链接 困难 🤩🤩🤩🤩🤩