一、错排问题:
n个数字打乱后每个数字都不在原位的方案数
二、公式推导 :
令n个数的错排数为D(n)
对于数字a, 假设它去了b的位置, 接下来考虑数字b
- b也去了a的位置, 那么a和b已经排好, 剩余n-2个数,这n-2个数都不能去自己的位置,其余位置都能去, 所以是n-2个数的错排问题, D(n-2)
- b没有去a的位置, 那么此时除开a, 剩余了n-1个数, 其中b只有a位置不能去, 除开ab的n-2个数都不能去自己的位置, 这等价于一个n-1个数的错排问题, D(n-1)
所以a去b的位置后,剩余的位置会有D(n-2)+D(n-1)种方案
a去b的位置,这个b有n-1个选择,所以D(n)=(n-1)*(D(n-1)+D(n-2))
三、代码实现:
long D(int n) {
if (n == 0 || n == 1) return 0;
if (n == 2) return 1;
return (n - 1) * (D(n - 1) + D(n - 2));
}
long D(int n) {
long[] dp = new long[n + 1];
dp[2] = 1;
for (int i = 3; i <= n; i++) {
dp[i] = (i - 1) * (dp[i - 1] + dp[i - 2]);
}
return dp[n];
}