「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战」。
n个数里面,形成k个逆序对(降序对)的有几个,求逆序对有多少种排列
一、分析
dp[i][j]:有i个数,所有排列的情况下,有j个逆序对(降序对)
n = 3,k = 2
1,2,3
1,2,3 1到2,1到3,2到3,0个逆序对(降序对)
1,3,2 1到3,1到2,3到2,1个逆序对(降序对)
2,1,3 2到1,2到3,1到3,1个逆序对(降序对)
2,3,1 2到3,2到1,3到1,2个逆序对 (降序对)√
3,1,2 3到1,3到2,1到2,2个逆序对 (降序对)√
3,2,1 3到2,3到1,2到1,3个逆序对(降序对)
n行k列,推出第一列全是1,第一行从第二列开始全是0
例如dp[5][3]:(12345)5个数,3个降序对
有如下情况:
dp[4][3]:(1234),3个降序对,5在最右边abcd5dp[4][2]:(1234),2个降序对,5在倒数第二位置abc5d(5到d)dp[4][1]:(1234),1个降序对,5在倒数第三位置ab5cd(5到c,5到d)dp[4][0]:(1234),0个降序对,5在倒数第二位置a5bcd(5到b,5到c,5到d)
斜率优化:
dp[5][3] = dp[4][3210]
dp[5][4] = dp[4][43210] = dp[4][4] + dp[5][3]
推出 j<i:dp[i][j] = dp[i-1][j] + dp[i][j-1]
dp[5][7] = dp[4][7...3]
dp[5][8] = dp[4][8...4] = dp[4][8] + dp[5][7] - dp[4][3]
推出 j≥i:dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-i]
二、实现
public static int kInversePairs(int n, int k) {
if (n < 1 || k < 0) {
return 0;
}
int[][] dp = new int[n + 1][k + 1];
dp[0][0] = 1;
int mod = 1000000007;
for (int i = 1; i <= n; i++) {
dp[i][0] = 1;
for (int j = 1; j <= k; j++) {
dp[i][j] = (dp[i][j - 1] + dp[i - 1][j]) % mod;
if (j >= i) {
dp[i][j] = (dp[i][j] - dp[i - 1][j - i] + mod) % mod;
}
}
}
return dp[n][k];
}
三、总结
样本对应模型,往往答案跟结尾有关