返回介绍

solution / 0600-0699 / 0629.K Inverse Pairs Array / README

发布于 2024-06-17 01:03:36 字数 4424 浏览 0 评论 0 收藏 0

629. K 个逆序对数组

English Version

题目描述

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

给你两个整数 n 和 k,找出所有包含从 1 到 n 的数字,且恰好拥有 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

解法

方法一:动态规划 + 前缀和

我们定义 $f[i][j]$ 表示数组长度为 $i$,逆序对数为 $j$ 的数组个数。初始时 $f[0][0] = 1$,其余 $f[i][j] = 0$。

接下来我们考虑如何得到 $f[i][j]$。

假设前 $i-1$ 个数已经确定,现在要插入数字 $i$,我们讨论 $i$ 插入到每个位置的情况:

  • 如果 $i$ 插入到第 $1$ 个位置,那么逆序对增加了 $i-1$ 个,所以 $f[i][j]+=f[i-1][j-(i-1)]$。
  • 如果 $i$ 插入到第 $2$ 个位置,那么逆序对增加了 $i-2$ 个,所以 $f[i][j]+=f[i-1][j-(i-2)]$。
  • 如果 $i$ 插入到第 $i-1$ 个位置,那么逆序对增加了 $1$ 个,所以 $f[i][j]+=f[i-1][j-1]$。
  • 如果 $i$ 插入到第 $i$ 个位置,那么逆序对不变,所以 $f[i][j]+=f[i-1][j]$。

所以 $f[i][j]=\sum_{k=1}^{i}f[i-1][j-(i-k)]$。

我们注意到 $f[i][j]$ 的计算实际上涉及到前缀和,因此,我们可以使用前缀和优化计算过程。并且,由于 $f[i][j]$ 只与 $f[i-1][j]$ 有关,因此我们可以用一个一维数组来优化空间复杂度。

时间复杂度 $O(n \times k)$,空间复杂度 $O(k)$。其中 $n$ 和 $k$ 分别为数组长度和逆序对数。

class Solution:
  def kInversePairs(self, n: int, k: int) -> int:
    mod = 10**9 + 7
    f = [1] + [0] * k
    s = [0] * (k + 2)
    for i in range(1, n + 1):
      for j in range(1, k + 1):
        f[j] = (s[j + 1] - s[max(0, j - (i - 1))]) % mod
      for j in range(1, k + 2):
        s[j] = (s[j - 1] + f[j - 1]) % mod
    return f[k]
class Solution {
  public int kInversePairs(int n, int k) {
    final int mod = (int) 1e9 + 7;
    int[] f = new int[k + 1];
    int[] s = new int[k + 2];
    f[0] = 1;
    Arrays.fill(s, 1);
    s[0] = 0;
    for (int i = 1; i <= n; ++i) {
      for (int j = 1; j <= k; ++j) {
        f[j] = (s[j + 1] - s[Math.max(0, j - (i - 1))] + mod) % mod;
      }
      for (int j = 1; j <= k + 1; ++j) {
        s[j] = (s[j - 1] + f[j - 1]) % mod;
      }
    }
    return f[k];
  }
}
class Solution {
public:
  int kInversePairs(int n, int k) {
    int f[k + 1];
    int s[k + 2];
    memset(f, 0, sizeof(f));
    f[0] = 1;
    fill(s, s + k + 2, 1);
    s[0] = 0;
    const int mod = 1e9 + 7;
    for (int i = 1; i <= n; ++i) {
      for (int j = 1; j <= k; ++j) {
        f[j] = (s[j + 1] - s[max(0, j - (i - 1))] + mod) % mod;
      }
      for (int j = 1; j <= k + 1; ++j) {
        s[j] = (s[j - 1] + f[j - 1]) % mod;
      }
    }
    return f[k];
  }
};
func kInversePairs(n int, k int) int {
  f := make([]int, k+1)
  s := make([]int, k+2)
  f[0] = 1
  for i, x := range f {
    s[i+1] = s[i] + x
  }
  const mod = 1e9 + 7
  for i := 1; i <= n; i++ {
    for j := 1; j <= k; j++ {
      f[j] = (s[j+1] - s[max(0, j-(i-1))] + mod) % mod
    }
    for j := 1; j <= k+1; j++ {
      s[j] = (s[j-1] + f[j-1]) % mod
    }
  }
  return f[k]
}
function kInversePairs(n: number, k: number): number {
  const f: number[] = new Array(k + 1).fill(0);
  f[0] = 1;
  const s: number[] = new Array(k + 2).fill(1);
  s[0] = 0;
  const mod: number = 1e9 + 7;
  for (let i = 1; i <= n; ++i) {
    for (let j = 1; j <= k; ++j) {
      f[j] = (s[j + 1] - s[Math.max(0, j - (i - 1))] + mod) % mod;
    }
    for (let j = 1; j <= k + 1; ++j) {
      s[j] = (s[j - 1] + f[j - 1]) % mod;
    }
  }
  return f[k];
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文