Derangement 是 n 个元素的排列,因此没有元素出现在其原始位置。例如,{0, 1, 2, 3} 的错位是 {2, 3, 1, 0}。
给定一个数 n,找出一组 n 个元素的乱序总数。
例子 :
Input: n = 2
Output: 1
For two elements say {0, 1}, there is only one
possible derangement {1, 0}
Input: n = 3
Output: 2
For three elements say {0, 1, 2}, there are two
possible derangements {2, 0, 1} and {1, 2, 0}
Input: n = 4
Output: 9
For four elements say {0, 1, 2, 3}, there are 9
possible derangements {1, 0, 3, 2} {1, 2, 3, 0}
{1, 3, 0, 2}, {2, 3, 0, 1}, {2, 0, 3, 1}, {2, 3,
1, 0}, {3, 0, 1, 2}, {3, 2, 0, 1} and {3, 2, 1, 0}
令 countDer(n) 为 n 个元素的紊乱计数。下面是它的递归关系。
countDer(n) = (n - 1) * [countDer(n - 1) + countDer(n - 2)]
上述递归关系如何工作?
元素 0 有 n – 1 种方式(这解释了与 n – 1 的乘法)。
将0 置于索引 i 处。现在有两种可能性,这取决于元素 i 是否被放置在 0 作为回报。
- i 被放置在 0:这种情况相当于解决 n-2 个元素的问题,因为两个元素刚刚交换了它们的位置。
- i 未放置在 0:这种情况相当于解决 n-1 个元素的问题,因为现在有 n-1 个元素,n-1 个位置,每个元素都有 n-2 个选择
以下是基于上述递归公式的简单解决方案:
C++
// A Naive Recursive C++ program
// to count derangements
#include
using namespace std;
int countDer(int n)
{
// Base cases
if (n == 1) return 0;
if (n == 2) return 1;
// countDer(n) = (n-1)[countDer(n-1) + der(n-2)]
return (n - 1) * (countDer(n - 1) + countDer(n - 2));
}
// Driver Code
int main()
{
int n = 4;
cout << "Count of Derangements is "
<< countDer(n);
return 0;
}
Java
// A Naive Recursive java
// program to count derangements
import java.io.*;
class GFG
{
// Function to count
// derangements
static int countDer(int n)
{
// Base cases
if (n == 1) return 0;
if (n == 2) return 1;
// countDer(n) = (n-1)[countDer(n-1) + der(n-2)]
return (n - 1) * (countDer(n - 1) +
countDer(n - 2));
}
// Driver Code
public static void main (String[] args)
{
int n = 4;
System.out.println( "Count of Derangements is "
+countDer(n));
}
}
// This code is contributed by vt_m
Python3
# A Naive Recursive Python3
# program to count derangements
def countDer(n):
# Base cases
if (n == 1): return 0
if (n == 2): return 1
# countDer(n) = (n-1)[countDer(n-1) + der(n-2)]
return (n - 1) * (countDer(n - 1) +
countDer(n - 2))
# Driver Code
n = 4
print("Count of Derangements is ", countDer(n))
# This code is contributed by Azkia Anam.
C#
// A Naive Recursive C#
// program to count derangements
using System;
class GFG
{
// Function to count
// derangements
static int countDer(int n)
{
// Base cases
if (n == 1) return 0;
if (n == 2) return 1;
// countDer(n) = (n-1)[countDer(n-1) + der(n-2)]
return (n - 1) * (countDer(n - 1) +
countDer(n - 2));
}
// Driver Code
public static void Main ()
{
int n = 4;
Console.Write( "Count of Derangements is " +
countDer(n));
}
}
// This code is contributed by nitin mittal.
PHP
Javascript
C++
// A Dynamic programming based C++
// program to count derangements
#include
using namespace std;
int countDer(int n)
{
// Create an array to store
// counts for subproblems
int der[n + 1] = {0};
// Base cases
der[1] = 0;
der[2] = 1;
// Fill der[0..n] in bottom up manner
// using above recursive formula
for (int i = 3; i <= n; ++i)
der[i] = (i - 1) * (der[i - 1] +
der[i - 2]);
// Return result for n
return der[n];
}
// Driver code
int main()
{
int n = 4;
cout << "Count of Derangements is "
<< countDer(n);
return 0;
}
Java
// A Dynamic programming based
// java program to count derangements
import java.io.*;
class GFG
{
// Function to count
// derangements
static int countDer(int n)
{
// Create an array to store
// counts for subproblems
int der[] = new int[n + 1];
// Base cases
der[1] = 0;
der[2] = 1;
// Fill der[0..n] in bottom up
// manner using above recursive
// formula
for (int i = 3; i <= n; ++i)
der[i] = (i - 1) * (der[i - 1] +
der[i - 2]);
// Return result for n
return der[n];
}
// Driver program
public static void main (String[] args)
{
int n = 4;
System.out.println("Count of Derangements is " +
countDer(n));
}
}
// This code is contributed by vt_m
Python3
# A Dynamic programming based Python3
# program to count derangements
def countDer(n):
# Create an array to store
# counts for subproblems
der = [0 for i in range(n + 1)]
# Base cases
der[1] = 0
der[2] = 1
# Fill der[0..n] in bottom up manner
# using above recursive formula
for i in range(3, n + 1):
der[i] = (i - 1) * (der[i - 1] +
der[i - 2])
# Return result for n
return der[n]
# Driver Code
n = 4
print("Count of Derangements is ", countDer(n))
# This code is contributed by Azkia Anam.
C#
// A Dynamic programming based
// C# program to count derangements
using System;
class GFG
{
// Function to count
// derangements
static int countDer(int n)
{
// Create an array to store
// counts for subproblems
int []der = new int[n + 1];
// Base cases
der[1] = 0;
der[2] = 1;
// Fill der[0..n] in bottom up
// manner using above recursive
// formula
for (int i = 3; i <= n; ++i)
der[i] = (i - 1) * (der[i - 1] +
der[i - 2]);
// Return result for n
return der[n];
}
// Driver code
public static void Main ()
{
int n = 4;
Console.Write("Count of Derangements is " +
countDer(n));
}
}
// This code is contributed by nitin mittal
PHP
Javascript
C++
// C++ implementation of the above
// approach
#include
using namespace std;
int countDer(int n)
{
// base case
if (n == 1 or n == 2) {
return n - 1;
}
// Variable for just storing
// previous values
int a = 0;
int b = 1;
// using above recursive formula
for (int i = 3; i <= n; ++i) {
int cur = (i - 1) * (a + b);
a = b;
b = cur;
}
// Return result for n
return b;
}
// Driver Code
int main()
{
cout << "Count of Dearrangements is " << countDer(4);
return 0;
}
// Code contributed by skagnihotri
Java
// Java implementation of the
// above approach
import java.io.*;
class GFG {
// Function to count derangements
static int countDer(int n) {
// Base case
if(n == 1 || n == 2) {
return n-1;
}
// Variable for storing prev values
int a = 0;
int b = 1;
// manner using above recursive formula
for (int i = 3; i <= n; ++i) {
int cur = (i-1)*(a+b);
a = b;
b = cur;
}
// Return result for n
return b;
}
// Driver Code
public static void main (String[] args)
{
int n = 4;
System.out.println("Count of Dearrangements is " +
countDer(n));
}
// Code contributed by skagnihotri
}
Python
# Python program to count derangements
def countDer(n):
# Base Case
if n == 1 or n == 2:
return n-1;
# Variables for storing prevoius values
a = 0
b = 1
# using above recursive formula
for i in range(3, n + 1):
cur = (i-1)*(a+b)
a = b
b = cur
# Return result for n
return b
# Driver Code
n = 4
print("Count of Dearrangements is ", countDer(n))
# Code contributed by skagnihotri
C#
// C# implementation of the above
// approach
using System;
class GFG{
// Function to count
// derangements
static int countDer(int n)
{
// Base case
if (n == 1 || n == 2)
{
return n - 1;
}
// Variable for just storing
// previous values
int a = 0;
int b = 1;
// Using above recursive formula
for(int i = 3; i <= n; ++i)
{
int cur = (i - 1) * (a + b);
a = b;
b = cur;
}
// Return result for n
return b;
}
// Driver code
public static void Main()
{
Console.Write("Count of Dearrangements is " +
countDer(4));
}
}
// This code is contributed by koulick_sadhu
Javascript
Count of Derangements is 9
时间复杂度:T(n) = T(n-1) + T(n-2) 这是指数。
我们可以观察到这个实现确实重复工作。例如,请参阅 countDer(5) 的递归树,countDer(3) 被评估两次。
cdr() ==> countDer()
cdr(5)
/ \
cdr(4) cdr(3)
/ \ / \
cdr(3) cdr(2) cdr(2) cdr(1)
一个有效的解决方案是使用动态规划将子问题的结果存储在数组中,并以自底向上的方式构建数组。
C++
// A Dynamic programming based C++
// program to count derangements
#include
using namespace std;
int countDer(int n)
{
// Create an array to store
// counts for subproblems
int der[n + 1] = {0};
// Base cases
der[1] = 0;
der[2] = 1;
// Fill der[0..n] in bottom up manner
// using above recursive formula
for (int i = 3; i <= n; ++i)
der[i] = (i - 1) * (der[i - 1] +
der[i - 2]);
// Return result for n
return der[n];
}
// Driver code
int main()
{
int n = 4;
cout << "Count of Derangements is "
<< countDer(n);
return 0;
}
Java
// A Dynamic programming based
// java program to count derangements
import java.io.*;
class GFG
{
// Function to count
// derangements
static int countDer(int n)
{
// Create an array to store
// counts for subproblems
int der[] = new int[n + 1];
// Base cases
der[1] = 0;
der[2] = 1;
// Fill der[0..n] in bottom up
// manner using above recursive
// formula
for (int i = 3; i <= n; ++i)
der[i] = (i - 1) * (der[i - 1] +
der[i - 2]);
// Return result for n
return der[n];
}
// Driver program
public static void main (String[] args)
{
int n = 4;
System.out.println("Count of Derangements is " +
countDer(n));
}
}
// This code is contributed by vt_m
蟒蛇3
# A Dynamic programming based Python3
# program to count derangements
def countDer(n):
# Create an array to store
# counts for subproblems
der = [0 for i in range(n + 1)]
# Base cases
der[1] = 0
der[2] = 1
# Fill der[0..n] in bottom up manner
# using above recursive formula
for i in range(3, n + 1):
der[i] = (i - 1) * (der[i - 1] +
der[i - 2])
# Return result for n
return der[n]
# Driver Code
n = 4
print("Count of Derangements is ", countDer(n))
# This code is contributed by Azkia Anam.
C#
// A Dynamic programming based
// C# program to count derangements
using System;
class GFG
{
// Function to count
// derangements
static int countDer(int n)
{
// Create an array to store
// counts for subproblems
int []der = new int[n + 1];
// Base cases
der[1] = 0;
der[2] = 1;
// Fill der[0..n] in bottom up
// manner using above recursive
// formula
for (int i = 3; i <= n; ++i)
der[i] = (i - 1) * (der[i - 1] +
der[i - 2]);
// Return result for n
return der[n];
}
// Driver code
public static void Main ()
{
int n = 4;
Console.Write("Count of Derangements is " +
countDer(n));
}
}
// This code is contributed by nitin mittal
PHP
Javascript
Count of Derangements is 9
时间复杂度: O(n)
辅助空间: O(n)
感谢 Utkarsh Trivedi 提出上述解决方案。
不使用额外空间的更有效的解决方案。
因为我们只需要记住两个先前的值所以,不是将值存储在数组中,而是可以使用两个变量来仅存储所需的先前值。
下面是上述方法的实现:
C++
// C++ implementation of the above
// approach
#include
using namespace std;
int countDer(int n)
{
// base case
if (n == 1 or n == 2) {
return n - 1;
}
// Variable for just storing
// previous values
int a = 0;
int b = 1;
// using above recursive formula
for (int i = 3; i <= n; ++i) {
int cur = (i - 1) * (a + b);
a = b;
b = cur;
}
// Return result for n
return b;
}
// Driver Code
int main()
{
cout << "Count of Dearrangements is " << countDer(4);
return 0;
}
// Code contributed by skagnihotri
Java
// Java implementation of the
// above approach
import java.io.*;
class GFG {
// Function to count derangements
static int countDer(int n) {
// Base case
if(n == 1 || n == 2) {
return n-1;
}
// Variable for storing prev values
int a = 0;
int b = 1;
// manner using above recursive formula
for (int i = 3; i <= n; ++i) {
int cur = (i-1)*(a+b);
a = b;
b = cur;
}
// Return result for n
return b;
}
// Driver Code
public static void main (String[] args)
{
int n = 4;
System.out.println("Count of Dearrangements is " +
countDer(n));
}
// Code contributed by skagnihotri
}
Python
# Python program to count derangements
def countDer(n):
# Base Case
if n == 1 or n == 2:
return n-1;
# Variables for storing prevoius values
a = 0
b = 1
# using above recursive formula
for i in range(3, n + 1):
cur = (i-1)*(a+b)
a = b
b = cur
# Return result for n
return b
# Driver Code
n = 4
print("Count of Dearrangements is ", countDer(n))
# Code contributed by skagnihotri
C#
// C# implementation of the above
// approach
using System;
class GFG{
// Function to count
// derangements
static int countDer(int n)
{
// Base case
if (n == 1 || n == 2)
{
return n - 1;
}
// Variable for just storing
// previous values
int a = 0;
int b = 1;
// Using above recursive formula
for(int i = 3; i <= n; ++i)
{
int cur = (i - 1) * (a + b);
a = b;
b = cur;
}
// Return result for n
return b;
}
// Driver code
public static void Main()
{
Console.Write("Count of Dearrangements is " +
countDer(4));
}
}
// This code is contributed by koulick_sadhu
Javascript
Count of Derangements is 9
时间复杂度: O(n)
辅助空间: O(1)
感谢 Shubham Kumar 提出上述解决方案。
参考:
https://en.wikipedia.org/wiki/Derangement
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。