在组合数学中,如果一个排列中所有元素都不在原先的位置上,那么这个排列就被称为 错位排列 。
给定一个从 1
到 n
升序排列的数组,返回 不同的错位排列 的数量 。由于答案可能非常大,你只需要将答案对 109+7
取余 输出即可。
示例 1:
输入: n = 3 输出: 2 解释: 原始的数组为 [1,2,3]。两个错位排列的数组为 [2,3,1] 和 [3,1,2]。
示例 2:
输入: n = 2 输出: 1
提示:
1 <= n <= 106
我们定义
对于长度为
- 放在第
$1$ 个位置,那么剩下的$i - 2$ 个位置可以有$f[i - 2]$ 种错位排列,因此总共有$(i - 1) \times f[i - 2]$ 种错位排列; - 不放在第
$1$ 个位置,那么相当于转化为了长度为$i - 1$ 的数组的错位排列,因此总共有$(i - 1) \times f[i - 1]$ 种错位排列。
综上,我们有如下状态转移方程:
最终答案即为
时间复杂度
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
}