629 K Inverse Pairs Array K个逆序对数组
Description:
For an integer array nums, an inverse pair is a pair of integers [i, j] where 0 <= i < j < nums.length and nums[i] > nums[j].
Given two integers n and k, return the number of different arrays consist of numbers from 1 to n such that there are exactly k inverse pairs. Since the answer can be huge, return it modulo 10^9 + 7.
Example:
Example 1:
Input: n = 3, k = 0
Output: 1
Explanation: Only the array [1,2,3] which consists of numbers from 1 to 3 has exactly 0 inverse pairs.
Example 2:
Input: n = 3, k = 1
Output: 2
Explanation: The array [1,3,2] and [2,1,3] have exactly 1 inverse pair.
Constraints:
1 <= n <= 1000
0 <= k <= 1000
题目描述:
给出两个整数 n 和 k,找出所有包含从 1 到 n 的数字,且恰好拥有 k 个逆序对的不同的数组的个数。
逆序对的定义如下:对于数组的第i个和第 j个元素,如果满i < j且 a[i] > a[j],则其为一个逆序对;否则不是。
由于答案可能很大,只需要返回 答案 mod 10^9 + 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]。
思路:
动态规划
dp[i][j] 表示对于 1-i 中逆序对有 j 个
dp[i][0] = 1, 表示顺序排列有 1 种情况
dp[i][j] = 0, 其中 j < 0
dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1] + ... + dp[i - 1][j - i + 1], 对于 1-(i - 1) 的任意排列, 将 i 插入任何一个位置都可以得到一个新的排列, 插到最后就是 dp[i - 1][j], 其余位置以此类推, 但是这个递推式的时间复杂度为 O(n ^ 2k), 需要进一步压缩
dp[i][j - 1] = dp[i - 1][j - 1] + dp[i - 1][j - 2] + ... + dp[i - 1][j - i], 与上面的式子比较可得 dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - 1]
这样就可以将时间复杂度压缩至 O(nk)
注意到 dp 只与前面一行有关, 可以用前缀和将空间复杂度优化到 O(k)
时间复杂度 O(nk), 空间复杂度 O(k)
代码:
C++:
class Solution
{
public:
int kInversePairs(int n, int k)
{
vector dp(k + 1, 0);
int mod = 1000000007;
dp.front() = 1;
for (int i = 2; i <= n; i++)
{
vector cur(dp);
for (int j = 1; j <= k; j++)
{
dp[j] = (dp[j - 1] + cur[j]) % mod;
if (j >= i) dp[j] = (dp[j] - cur[j - i] + mod) % mod;
}
}
return dp.back();
}
};
Java:
class Solution {
public int kInversePairs(int n, int k) {
int dp[][] = new int[n + 1][k + 1], mod = 1000000007;
for (int i = 0; i < n + 1; i++) dp[i][0] = 1;
for (int i = 1; i < n + 1; i++) for (int j = 1; j < k + 1; j++) dp[i][j] = ((dp[i - 1][j] + dp[i][j - 1] - (j - i > -1 ? dp[i - 1][j - i] : 0)) % mod + mod) % mod;
return dp[n][k];
}
}
Python:
class Solution:
def kInversePairs(self, n: int, k: int) -> int:
dp = [[1] + [0] * k for _ in range(n + 1)]
for i in range(1, n + 1):
for j in range(1, k + 1):
dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - (dp[i - 1][j - i] if j - i > -1 else 0)
return dp[n][k] % (10 ** 9 + 7)