📜  计数排列(排列,使得没有元素出现在其原始位置)

📅  最后修改于: 2021-04-26 06:28:55             🧑  作者: Mango

排列是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。

  1. i的位置为0:这种情况等效于解决n-2个元素的问题,因为两个元素刚刚交换了位置。
  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


输出
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

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


Java脚本


输出
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
输出
Count of Derangements is 9

时间复杂度: O(n)  
辅助空间: O(1)

感谢Shubham Kumar提出上述解决方案。

参考:
https://zh.wikipedia.org/wiki/排列