📜  重复给定数组的错位计数

📅  最后修改于: 2022-05-13 01:56:04.283000             🧑  作者: Mango

重复给定数组的错位计数

给定一个包含N个数字 ( N ≤ 20 ) 的数组arr[] ,任务是找到数组中可以重复数组元素的Derangements的数量。

例子:

朴素方法:解决此问题的最简单方法是生成所有可能的排列,并且对于每个排列,检查是否所有元素都未放置在其原始位置。如果发现为真,则增加计数。最后,打印计数。

时间复杂度: O(N! * N)
辅助空间: O(N)

高效方法:上述方法也可以使用动态编程位掩码进行优化,因为它具有重叠的子问题和最优的子结构。解决这个问题的想法是基于以下观察:

请按照以下步骤解决问题:

  • 定义一个大小为 (1 << N) 的dp数组并将其初始化为 -1 以存储所有 dp 状态。
  • 定义一个递归函数说countDerangements(i, mask)来计算错位的数量
    • 基本情况,如果i等于N ,则构建了有效的紊乱。
    • 如果dp[mask]不等于 -1,即已经访问过,则返回dp[mask]。
    • 使用变量j在范围[0, N-1]上进行迭代,并且在每次迭代中,如果未设置掩码中的第 j位并且如果A[i] != A[j] ,则
      • dp[mask]更新为dp[mask] = dp[mask] + countDerangements (i+1, mask | (<< j))
    • 最后,返回 dp[mask]。
  • 如果任何数字重复多次,则返回的答案必须除以该数字的频率,因为在不同位置交换相同的数字将导致相同的混乱。
  • 因此,检查所有数字的频率,如果它大于 1,则将答案除以数字的频率。
  • 这将是最终的答案。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Declaring a dp array
long long dp[1 << 20];
 
// Function to return
// the factorial of a number
long long factorial(int n)
{
    long long fact = 1;
    for (int i = 2; i <= n; ++i) {
        fact *= i;
    }
    return fact;
}
 
// Function to count the
// Number of derangements
long long countDerangements(int i, int mask,
                            int n, int A[])
{
    // If all the numbers are placed,
    // then return 1.
    if (mask == (1 << n) - 1) {
        return 1;
    }
 
    // If the state has already been computed,
    // then return it
    if (dp[mask] != -1) {
        return dp[mask];
    }
 
    dp[mask] = 0;
 
    // Check for all possible numbers
    // that can be placed in
    // the current position 'i'.
    for (int j = 0; j < n; ++j) {
 
        // If the current element arr[j]
        // Is not yet selected
        //(bit 'j' is unset in mask),
        // And if arr[i]!= arr[j]
        //(to ensure derangement).
        if (!(mask & (1 << j))
            and (A[i] != A[j])) {
 
            // Set the bit 'j' in mask and
            // Call the function
            // For index 'i + 1'.
            dp[mask] += countDerangements(
                i + 1, mask | (1 << j), n, A);
        }
    }
 
    // Return dp[mask]
    return dp[mask];
}
 
// Utility Function to count
// The number of derangements
long long UtilCountDerangements(int A[],
                                int N)
{
    // Initializing the dp array with -1.
    memset(dp, -1, sizeof dp);
 
    // HashMap to store the frequency
    // of each number.
    map frequencyMap;
    for (int i = 0; i < N; ++i) {
        ++frequencyMap[A[i]];
    }
 
    // Function call and storing
    // The return value in 'ans'.
    long long ans
        = countDerangements(0, 0, N, A);
 
    // Iterating through the HashMap
    for (auto itr : frequencyMap) {
 
        // Frequency of current number
        int times = itr.second;
 
        // If it occurs more than 1 time,
        // divide the answer by its frequency.
        if (times > 1) {
            ans /= factorial(times);
        }
    }
    return ans;
}
 
// Driver code
int main()
{
    // Input array
    int arr[] = { 1, 2, 2, 3, 3 };
 
    // Size of array
    int N = sizeof(arr) / sizeof(arr[0]);
    cout << UtilCountDerangements(arr, N);
    return 0;
}


Python3
# Python program for the above approach
 
# Declaring a dp array
dp = [-1]*(1 << 20)
 
# Function to return
# the factorial of a number
def factorial(n):
    fact = 1
    for i in range(2,n+1):
        fact *= i
    return fact
 
# Function to count the
# Number of derangements
def countDerangements(i,mask,n, A):
 
    # If all the numbers are placed,
    # then return 1.
    if (mask == (1 << n) - 1):
        return 1
 
    # If the state has already been computed,
    # then return it
    if (dp[mask] != -1):
        return dp[mask]
 
    dp[mask] = 0
 
    # Check for all possible numbers
    # that can be placed in
    # the current position 'i'.
    for j in range(n):
 
        # If the current element arr[j]
        # Is not yet selected
        #(bit 'j' is unset in mask),
        # And if arr[i]!= arr[j]
        #(to ensure derangement).
        if (mask & (1 << j) == 0 and (A[i] != A[j])):
 
            # Set the bit 'j' in mask and
            # Call the function
            # For index 'i + 1'.
            dp[mask] += countDerangements(i + 1, mask | (1 << j), n, A)
 
    # Return dp[mask]
    return dp[mask]
 
# Utility Function to count
# The number of derangements
def UtilCountDerangements(A,N):
 
    # HashMap to store the frequency
    # of each number.
   frequencyMap = {}
   for i in range(N):
      if A[i] in frequencyMap:
         frequencyMap[A[i]] = frequencyMap[A[i]]+1
      else:
         frequencyMap[A[i]] = 1
 
    # Function call and storing
    # The return value in 'ans'.
   ans = countDerangements(0, 0, N, A)
 
    # Iterating through the HashMap
   for key,value in frequencyMap.items():
 
        # Frequency of current number
      times = value
 
        # If it occurs more than 1 time,
        # divide the answer by its frequency.
      if (times > 1):
         ans = ans // factorial(times)
   return ans
 
# Driver code
 
# Input array
arr = [ 1, 2, 2, 3, 3 ]
 
# Size of array
N = len(arr)
print(UtilCountDerangements(arr, N))
 
# This code is contributed by shinjanpatra.


C#
// C# program of the above approach
using System;
using System.Collections.Generic;
 
class GFG
{
 
// Declaring a dp array
static int[] dp = new int[1 << 20];
 
// Function to return
// the factorial of a number
static int factorial(int n)
{
    int fact = 1;
    for (int i = 2; i <= n; ++i) {
        fact *= i;
    }
    return fact;
}
 
// Function to count the
// Number of derangements
static int countDerangements(int i, int mask,
                            int n, int[] A)
{
    // If all the numbers are placed,
    // then return 1.
    if (mask == (1 << n) - 1) {
        return 1;
    }
 
    // If the state has already been computed,
    // then return it
    if (dp[mask] != -1) {
        return dp[mask];
    }
 
    dp[mask] = 0;
 
    // Check for all possible numbers
    // that can be placed in
    // the current position 'i'.
    for (int j = 0; j < n; ++j) {
 
        // If the current element arr[j]
        // Is not yet selected
        //(bit 'j' is unset in mask),
        // And if arr[i]!= arr[j]
        //(to ensure derangement).
        if ((mask & (1 << j)) == 0
            && (A[i] != A[j])) {
 
            // Set the bit 'j' in mask and
            // Call the function
            // For index 'i + 1'.
            dp[mask] += countDerangements(
                i + 1, mask | (1 << j), n, A);
        }
    }
 
    // Return dp[mask]
    return dp[mask];
}
 
// Utility Function to count
// The number of derangements
static int UtilCountDerangements(int[] A,
                                int N)
{
    // Initializing the dp array with -1.
    for(int i = 0;i<(1 << 20); i++)
    {
        dp[i]=-1;
    }
 
    // HashMap to store the frequency
    // of each number.
    Dictionary frequencyMap = new Dictionary();
     
    for (int i = 0; i < N; i++) {
  
        if(frequencyMap.ContainsKey(A[i])){
            frequencyMap[A[i]] = frequencyMap[A[i]] + 1;
        }else{
            frequencyMap.Add(A[i], 1);
        }
    }
 
  
 
    // Function call and storing
    // The return value in 'ans'.
    int ans
        = countDerangements(0, 0, N, A);
 
    // Iterating through the HashMap
    foreach (KeyValuePair itr in frequencyMap)
    {
 
        // Frequency of current number
        int times = itr.Value;
 
        // If it occurs more than 1 time,
        // divide the answer by its frequency.
        if (times > 1) {
            ans /= factorial(times);
        }
    }
    return ans;
}
 
// Driver Code
public static void Main()
{
   
    // Input array
    int[] arr = { 1, 2, 2, 3, 3 };
 
    // Size of array
    int N = arr.Length;
    Console.Write( UtilCountDerangements(arr, N));
}
}
 
// This code is contributed by sanjoy_62.


Javascript



输出
4

时间复杂度: O(N * 2 N )
辅助空间: O( 2N )