友情支持

如果您觉得这个笔记对您有所帮助,看在D瓜哥码这么多字的辛苦上,请友情支持一下,D瓜哥感激不尽,😜

支付宝

微信

有些打赏的朋友希望可以加个好友,欢迎关注D 瓜哥的微信公众号,这样就可以通过公众号的回复直接给我发信息。

wx jikerizhi

公众号的微信号是: jikerizhi因为众所周知的原因,有时图片加载不出来。 如果图片加载不出来可以直接通过搜索微信号来查找我的公众号。

629. K 个逆序对数组

对于一个整数数组 nums逆序对是一对满足 0 <= i < j < nums.lengthnums[i] > nums[j] 的整数对 [i, j]

给你两个整数 nk,找出所有包含从 1n 的数字,且恰好拥有 k逆序对 的不同的数组的个数。由于答案可能很大,只需要返回对 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 个逆序对。

提示:

  • 1 <= n <= 1000

  • 0 <= k <= 1000

思路分析

有点懵逼,似懂非懂。

从暴力破解,再加备忘录,最后到动态规划,这样的思路比较容易理解。

  • 一刷(暴力破解)

  • 一刷(备忘录)

  • 一刷(动态规划)

  • 一刷(动态规划)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * @author D瓜哥 · https://www.diguage.com
 * @since 2026-04-09 19:55:53
 */
public int kInversePairs(int n, int k) {
  return dfs(n, k);
}

private int dfs(int n, int k) {
  if (k > n * (n - 1) / 2) {
    return 0;
  }
  if (n == 1) {
    return k == 0 ? 1 : 0;
  }
  int MOD = 1_000_000_007;
  int result = 0;
  for (int i = Math.max(0, k - n + 1); i <= k; i++) {
    result += dfs(n - 1, i) % MOD;
    result %= MOD;
  }
  return result;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
 * @author D瓜哥 · https://www.diguage.com
 * @since 2026-04-09 20:22:16
 */
public int kInversePairs(int n, int k) {
  int[][] memo = new int[n + 1][k + 1];
  for (int[] m : memo) {
    Arrays.fill(m, -1);
  }
  return dfs(n, k, memo);
}

private int dfs(int n, int k, int[][] memo) {
  if (k > n * (n - 1) / 2) {
    return 0;
  }
  if (n == 1) {
    return k == 0 ? 1 : 0;
  }
  if (memo[n][k] != -1) {
    return memo[n][k];
  }
  int MOD = 1_000_000_007;
  int result = 0;
  for (int i = Math.max(0, k - n + 1); i <= k; i++) {
    result += dfs(n - 1, i, memo) % MOD;
    result %= MOD;
  }
  return memo[n][k] = result;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/**
 * @author D瓜哥 · https://www.diguage.com
 * @since 2026-04-09 20:25:24
 */
public int kInversePairs(int n, int k) {
  int[][] dp = new int[n + 1][k + 1];
  dp[1][0] = 1;
  int MOD = 1_000_000_007;
  for (int i = 2; i <= n; i++) {
    for (int j = 0; j <= Math.min(k, i * (i - 1) / 2); j++) {
      for (int l = Math.max(0, j - i + 1); l <= j; l++) {
        dp[i][j] = (dp[i][j] + dp[i - 1][l]) % MOD;
      }
    }
  }
  return dp[n][k];
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * @author D瓜哥 · https://www.diguage.com
 * @since 2026-04-09 20:35:42
 */
public int kInversePairs(int n, int k) {
  // dp[i][j] = dp[i-1][j] + dp[i-1][j-1] + ... + dp[i-1][j-i-1]
  // dp[i][j-1] =            dp[i-1][j-1] + ... + dp[i-1][j-1-(i-1-1)] + dp[i-1][j-1-i-1]
  // dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1-i-1]
  long[][] dp = new long[n + 1][k + 1];
  dp[1][0] = 1;
  int MOD = 1_000_000_007;
  for (int i = 2; i <= n; i++) {
    for (int j = 0; j <= Math.min(k, i * (i - 1) / 2); j++) {
      // dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-i]
      // 奇怪:为啥这里要加 MOD ?
      dp[i][j] = (dp[i - 1][j] + (j >= 1 ? dp[i][j - 1] : 0)
        - (j >= i ? dp[i - 1][j - i] : 0) + MOD) % MOD;
    }
  }
  return (int) dp[n][k];
}