题目:
给出两个整数 n 和 k,找出所有包含从 1 到 n 的数字,且恰好拥有 k 个逆序对的不同的数组的个数。
逆序对的定义如下:对于数组的第i个和第 j个元素,如果满i < j且 a[i] > a[j],则其为一个逆序对;否则不是。
由于答案可能很大,只需要返回 答案 mod 109 + 7 的值。
算法:
本题考查动态规划。
状态转移方程:
【f(n)(k)需要k个逆序对,由第n个往f(n-1)的不同位置插入的到k个逆序对。n和前n-1个数最多构造n-1个逆序对,所以f(n - 1)最少要能提供k-(n-1))个逆序对,即f(n-1)(k - (n - 1))】
f(n)(k) = f(n-1)(k) + f(n-1)(k - 1) + f(n-1)(k - 2) + f(n-1)(k - (n - 1))
f(n)(k - 1) = f(n-1)(k -1) + f(n-1)(k - 2) + f(n-1)(k - 3) + f(n-1)(k - 1 - (n - 1))
得到:
f(n)(k)
= f(n)(k - 1) + f(n-1)(k) - f(n-1)(k - 1 - (n - 1))
= f(n)(k - 1) + f(n-1)(k) - f(n-1)(k - n)
参考:
leetcode.cn/problems/k-…
func kInversePairs(n int, k int) int {
MOD := 1000000007
dp := make([][]int, n + 1)
for i := range dp {
dp[i] = make([]int, k + 1)
}
dp[1][0] = 1
// i是n的
for i := 2; i <= n; i ++ {
maxParis := min(k, (i - 1) * i / 2)
// j 是逆序对的数量
for j := 0; j <= maxParis; j ++ {
tmp1, tmp2 := 0, 0
if j - 1 >= 0 {
tmp1 = dp[i][j - 1]
}
if j - i >= 0 {
tmp2 = dp[i - 1][j - i]
}
dp[i][j] = (tmp1 + dp[i - 1][j] - tmp2 + MOD) % MOD
// }
}
}
return dp[n][k]
}
func max(i , j int) int {
if i > j {
return i
}
return j
}
func min(i , j int) int {
if i < j {
return i
}
return j
}