634. 寻找数组的错位排列 🔒
题目描述
在组合数学中,如果一个排列中所有元素都不在原先的位置上,那么这个排列就被称为 错位排列 。
给定一个从 1
到 n
升序排列的数组,返回 不同的错位排列 的数量 。由于答案可能非常大,你只需要将答案对 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]$。注意答案的取模操作。
时间复杂度 $O(n)$,其中 $n$ 为数组的长度。空间复杂度 $O(1)$。
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 8 9 10 11 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
1 2 3 4 5 6 7 8 9 |
|
方法二:动态规划(空间优化)
我们发现,状态转移方程中只与 $f[i - 1]$ 和 $f[i - 2]$ 有关,因此我们可以使用两个变量 $a$ 和 $b$ 来分别表示 $f[i - 1]$ 和 $f[i - 2]$,从而将空间复杂度降低到 $O(1)$。
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
1 2 3 4 5 6 7 8 |
|