文章目录
题目
给出两个整数 n 和 k,找出所有包含从 1 到 n 的数字,且恰好拥有 k 个逆序对的不同的数组的个数。
逆序对的定义如下:对于数组的第i个和第 j个元素,如果满i < j且 a[i] > a[j],则其为一个逆序对;否则不是。
由于答案可能很大,只需要返回 答案 mod 109 + 7 的值。
示例 1:
输入: n = 3, k = 0
输出: 1
解释:
只有数组 [1,2,3] 包含了从1到3的整数并且正好拥有 0 个逆序对
示例 2:
输入: n = 3, k = 1
输出: 2
解释:
数组 [1,3,2] 和 [2,1,3] 都有 1 个逆序对。
说明:
n 的范围是 [1, 1000] 并且 k 的范围是 [0, 1000]。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/k-inverse-pairs-array
一、解题思路
dp[n][k]表示1到n的数字中,逆序对的个数为k的不同数组的个数
如果n放在最后的位置,那么k个逆序对就在前面n-1的数组中
如果n放在倒数第二个位置,那么就会出现一个逆序对,则前面n-1的数组中有k-1个逆序对
如果n放在第一个位置,那么就会出现n-1个逆序对,则前面n-1的数组中有k-n+1个逆序对
递推关系:
dp[n][k] = dp[n - 1][k] + dp[n - 1][k - 1] + dp[n - 1][k - 2] + ... + dp[n - 1][k+1-n+1] + dp[n -1][k - n + 1]
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 - 1][k + 1] + dp[n][k] - dp[n - 1][k - n + 1]
二、结果
1.注意点
由于dp[n][k]可能出现负数,因此要进行取模运算dp[n][k] = dp[n][k] + MOD
2.Java代码
代码如下(示例):
class Solution {
public int kInversePairs(int n, int k) {
long[][] dp = new long[n + 1][k + 1];
if(k > n*(n - 1) / 2 || k < 0)
return 0;
if(k == 0 || k == n *(n - 1) / 2)
return 1;
int mod = 1000000007;
dp[2][0] = 1;
dp[2][1] = 1;
for(int i = 3 ; i <= n ; i ++){
dp[i][0] = 1;
for(int j = 1 ; j <= Math.min(k, n * (n - 1) / 2); j ++){
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
if(j >= i)
dp[i][j] -= dp[i - 1][j - i];
dp[i][j] = (dp[i][j] + mod) % mod; //处理dp[i][j]为负数的情况
}
}
return (int)dp[n][k];
}
}
总结
hard,加油加油