返回介绍

solution / 0600-0699 / 0634.Find the Derangement of An Array / README

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

634. 寻找数组的错位排列

English Version

题目描述

在组合数学中,如果一个排列中所有元素都不在原先的位置上,那么这个排列就被称为 错位排列

给定一个从 1n 升序排列的数组,返回 _不同的错位排列 的数量 _。由于答案可能非常大,你只需要将答案对 109+7 取余 输出即可。

 

示例 1:

输入: n = 3
输出: 2
解释: 原始的数组为 [1,2,3]。两个错位排列的数组为 [2,3,1] 和 [3,1,2]。

示例 2:

输入: n = 2
输出: 1

 

提示:

  • 1 <= n <= 106

解法

方法一:动态规划

我们定义 $f[i]$ 表示长度为 $i$ 的数组的错位排列的数量。初始时 $f[0] = 1$, $f[1] = 0$。答案即为 $f[n]$。

对于长度为 $i$ 的数组,我们考虑将数字 $1$ 放在哪个位置,假设放在第 $j$ 个位置,这里有 $i-1$ 种选择,那么接下来数字 $j$ 可以有两种选择:

  • 放在第 $1$ 个位置,那么剩下的 $i - 2$ 个位置可以有 $f[i - 2]$ 种错位排列,因此总共有 $(i - 1) \times f[i - 2]$ 种错位排列;
  • 不放在第 $1$ 个位置,那么相当于转化为了长度为 $i - 1$ 的数组的错位排列,因此总共有 $(i - 1) \times f[i - 1]$ 种错位排列。

综上,我们有如下状态转移方程:

$$ f[i] = (i - 1) \times (f[i - 1] + f[i - 2]) $$

最终答案即为 $f[n]$。注意答案的取模操作。

我们发现,状态转移方程中只与 $f[i - 1]$ 和 $f[i - 2]$ 有关,因此我们可以使用两个变量 $a$ 和 $b$ 来分别表示 $f[i - 1]$ 和 $f[i - 2]$,从而将空间复杂度降低到 $O(1)$。

时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组的长度。

class Solution:
  def findDerangement(self, n: int) -> int:
    mod = 10**9 + 7
    f = [1] + [0] * n
    for i in range(2, n + 1):
      f[i] = (i - 1) * (f[i - 1] + f[i - 2]) % mod
    return f[n]
class Solution {
  public int findDerangement(int n) {
    long[] f = new long[n + 1];
    f[0] = 1;
    final int mod = (int) 1e9 + 7;
    for (int i = 2; i <= n; ++i) {
      f[i] = (i - 1) * (f[i - 1] + f[i - 2]) % mod;
    }
    return (int) f[n];
  }
}
class Solution {
public:
  int findDerangement(int n) {
    long long f[n + 1];
    memset(f, 0, sizeof(f));
    f[0] = 1;
    const int mod = 1e9 + 7;
    for (int i = 2; i <= n; i++) {
      f[i] = (i - 1LL) * (f[i - 1] + f[i - 2]) % mod;
    }
    return f[n];
  }
};
func findDerangement(n int) int {
  f := make([]int, n+1)
  f[0] = 1
  const mod = 1e9 + 7
  for i := 2; i <= n; i++ {
    f[i] = (i - 1) * (f[i-1] + f[i-2]) % mod
  }
  return f[n]
}

方法二

class Solution:
  def findDerangement(self, n: int) -> int:
    mod = 10**9 + 7
    a, b = 1, 0
    for i in range(2, n + 1):
      a, b = b, ((i - 1) * (a + b)) % mod
    return b
class Solution {
  public int findDerangement(int n) {
    final int mod = (int) 1e9 + 7;
    long a = 1, b = 0;
    for (int i = 2; i <= n; ++i) {
      long c = (i - 1) * (a + b) % mod;
      a = b;
      b = c;
    }
    return (int) b;
  }
}
class Solution {
public:
  int findDerangement(int n) {
    long long a = 1, b = 0;
    const int mod = 1e9 + 7;
    for (int i = 2; i <= n; ++i) {
      long long c = (i - 1) * (a + b) % mod;
      a = b;
      b = c;
    }
    return b;
  }
};
func findDerangement(n int) int {
  a, b := 1, 0
  const mod = 1e9 + 7
  for i := 2; i <= n; i++ {
    a, b = b, (i-1)*(a+b)%mod
  }
  return b
}

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

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

发布评论

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