Count of Derangements of given Array with Repetition
Last Updated :
26 Apr, 2022
Given an array arr[] of N numbers (N ≤ 20), the task is to find the number of Derangements of the array where array elements can be repeated.
A derangement is a permutation of N elements, such that no element appears in its original position. For example, a derangement of {0, 1, 2, 3} is {2, 3, 1, 0}.
Examples:
Input: arr[] = {0, 0, 1}
Output: 0
Explanation: All permutations of the array are – {0, 0, 1}, {0, 1, 0} and{1, 0, 0}.
In each permutation, there is atleast one number which is placed in the same position as in the input array.
Hence the answer is 0.
Input: arr[] = {1, 1, 0, 0}
Output: 1
Explanation: The only derangement is {0, 0, 1, 1}
Input: arr[] = {1, 2, 2, 3, 3}
Output: 4
Explanation: The derangements are {2, 3, 3, 1, 2}, {2, 3, 3, 2, 1}, {3, 3, 1, 2, 2} and {3, 1, 3, 2, 2}
Naive Approach: The simplest approach to solve this problem is to generate all possible permutations and for each permutation, check if all the elements are not placed in their original position. If found to be true, then increment the count. Finally, print the count.
Time Complexity: O(N! * N)
Auxiliary Space: O(N)
Efficient Approach: The above approach can also be optimized using dynamic programming and bitmasking as it has overlapping subproblems and optimal substructure. The idea to solve this problem is based on the following observations:
- For each index of Arr[] the idea is to choose a not selected array element of Arr[] and using bitmasking to keep track of the already selected elements of Arr[]. The selected element must also be not equal to the current element to ensure derangement.
- dp(i, mask) stores the result from the ‘i’th position till the end, with bitmask ‘mask’ denoting the already selected elements of array Arr[] till the ‘i-1’th position.
- Since the current position can be determined by the count of set bits of mask, reduce dp(i, mask) to dp(mask).
- Then the transition from one state to another state can be defined as:
- For all j in the range [0, N – 1]:
- If the jth bit of mask is not set and if A[i] != A[j], then, dp(i, mask) += dp(i + 1, mask|(1<<j)).
Follow the steps below to solve the problem:
- Define a dp array of size (1 << N) and initialize it with -1 to store all dp states.
- Define a recursive function say countDerangements(i, mask) to count the number of derangements
- Base case, if i is equal to N then a valid derangement has been constructed.
- If dp[mask] is not equal to -1 i.e already visited then return dp[mask].
- Iterate over the range [0, N-1] using variable j and in each iteration, if jth bit in the mask is not set and if A[i] != A[j], then,
- Update dp[mask] as dp[mask] = dp[mask] + countDerangements (i+1, mask | (<< j)).
- Finally, return dp[mask].
- If any number is repeated more than once, then the answer returned has to be divided by the frequency of that number because the same number swapped in different positions will result in the same derangement.
- Hence, check for the frequency of all numbers and divide the answer by the frequency of a number if it is greater than 1.
- This will be the final answer.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
long long dp[1 << 20];
long long factorial( int n)
{
long long fact = 1;
for ( int i = 2; i <= n; ++i) {
fact *= i;
}
return fact;
}
long long countDerangements( int i, int mask,
int n, int A[])
{
if (mask == (1 << n) - 1) {
return 1;
}
if (dp[mask] != -1) {
return dp[mask];
}
dp[mask] = 0;
for ( int j = 0; j < n; ++j) {
if (!(mask & (1 << j))
and (A[i] != A[j])) {
dp[mask] += countDerangements(
i + 1, mask | (1 << j), n, A);
}
}
return dp[mask];
}
long long UtilCountDerangements( int A[],
int N)
{
memset (dp, -1, sizeof dp);
map< int , int > frequencyMap;
for ( int i = 0; i < N; ++i) {
++frequencyMap[A[i]];
}
long long ans
= countDerangements(0, 0, N, A);
for ( auto itr : frequencyMap) {
int times = itr.second;
if (times > 1) {
ans /= factorial(times);
}
}
return ans;
}
int main()
{
int arr[] = { 1, 2, 2, 3, 3 };
int N = sizeof (arr) / sizeof (arr[0]);
cout << UtilCountDerangements(arr, N);
return 0;
}
|
Java
import java.util.*;
public class Main
{
static int [] dp = new int [ 1 << 20 ];
static int factorial( int n)
{
int fact = 1 ;
for ( int i = 2 ; i <= n; ++i) {
fact *= i;
}
return fact;
}
static int countDerangements( int i, int mask,
int n, int [] A)
{
if (mask == ( 1 << n) - 1 ) {
return 1 ;
}
if (dp[mask] != - 1 ) {
return dp[mask];
}
dp[mask] = 0 ;
for ( int j = 0 ; j < n; ++j) {
if ((mask & ( 1 << j)) == 0
&& (A[i] != A[j])) {
dp[mask] += countDerangements(
i + 1 , mask | ( 1 << j), n, A);
}
}
return dp[mask];
}
static int UtilCountDerangements( int [] A,
int N)
{
for ( int i = 0 ;i<( 1 << 20 ); i++)
{
dp[i]=- 1 ;
}
HashMap<Integer,
Integer> frequencyMap = new HashMap<Integer,
Integer>();
for ( int i = 0 ; i < N; i++) {
if (frequencyMap.containsKey(A[i])){
frequencyMap.put(A[i], frequencyMap.get(A[i])+ 1 );
} else {
frequencyMap.put(A[i], 1 );
}
}
int ans
= countDerangements( 0 , 0 , N, A);
for (Map.Entry<Integer,Integer> itr : frequencyMap.entrySet())
{
int times = itr.getValue();
if (times > 1 ) {
ans /= factorial(times);
}
}
return ans;
}
public static void main(String[] args)
{
int [] arr = { 1 , 2 , 2 , 3 , 3 };
int N = arr.length;
System.out.println( UtilCountDerangements(arr, N));
}
}
|
Python3
dp = [ - 1 ] * ( 1 << 20 )
def factorial(n):
fact = 1
for i in range ( 2 ,n + 1 ):
fact * = i
return fact
def countDerangements(i,mask,n, A):
if (mask = = ( 1 << n) - 1 ):
return 1
if (dp[mask] ! = - 1 ):
return dp[mask]
dp[mask] = 0
for j in range (n):
if (mask & ( 1 << j) = = 0 and (A[i] ! = A[j])):
dp[mask] + = countDerangements(i + 1 , mask | ( 1 << j), n, A)
return dp[mask]
def UtilCountDerangements(A,N):
frequencyMap = {}
for i in range (N):
if A[i] in frequencyMap:
frequencyMap[A[i]] = frequencyMap[A[i]] + 1
else :
frequencyMap[A[i]] = 1
ans = countDerangements( 0 , 0 , N, A)
for key,value in frequencyMap.items():
times = value
if (times > 1 ):
ans = ans / / factorial(times)
return ans
arr = [ 1 , 2 , 2 , 3 , 3 ]
N = len (arr)
print (UtilCountDerangements(arr, N))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int [] dp = new int [1 << 20];
static int factorial( int n)
{
int fact = 1;
for ( int i = 2; i <= n; ++i) {
fact *= i;
}
return fact;
}
static int countDerangements( int i, int mask,
int n, int [] A)
{
if (mask == (1 << n) - 1) {
return 1;
}
if (dp[mask] != -1) {
return dp[mask];
}
dp[mask] = 0;
for ( int j = 0; j < n; ++j) {
if ((mask & (1 << j)) == 0
&& (A[i] != A[j])) {
dp[mask] += countDerangements(
i + 1, mask | (1 << j), n, A);
}
}
return dp[mask];
}
static int UtilCountDerangements( int [] A,
int N)
{
for ( int i = 0;i<(1 << 20); i++)
{
dp[i]=-1;
}
Dictionary< int , int > frequencyMap = new Dictionary< int , int >();
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);
}
}
int ans
= countDerangements(0, 0, N, A);
foreach (KeyValuePair< int , int > itr in frequencyMap)
{
int times = itr.Value;
if (times > 1) {
ans /= factorial(times);
}
}
return ans;
}
public static void Main()
{
int [] arr = { 1, 2, 2, 3, 3 };
int N = arr.Length;
Console.Write( UtilCountDerangements(arr, N));
}
}
|
Javascript
<script>
let dp = new Array(1 << 20).fill(-1);
function factorial(n) {
let fact = 1;
for (let i = 2; i <= n; ++i) {
fact *= i;
}
return fact;
}
function countDerangements(i, mask,
n, A)
{
if (mask == (1 << n) - 1) {
return 1;
}
if (dp[mask] != -1) {
return dp[mask];
}
dp[mask] = 0;
for (let j = 0; j < n; ++j) {
if (!(mask & (1 << j))
&& (A[i] != A[j])) {
dp[mask] += countDerangements(
i + 1, mask | (1 << j), n, A);
}
}
return dp[mask];
}
function UtilCountDerangements(A, N) {
let frequencyMap = new Map();
for (let i = 0; i < N; ++i) {
if (frequencyMap.has(A[i])) {
frequencyMap.set(A[i], frequencyMap.get(A[i]) + 1)
}
else {
frequencyMap.set(A[i], 1)
}
}
let ans
= countDerangements(0, 0, N, A);
for (let [key, val] of frequencyMap) {
let times = val;
if (times > 1) {
ans /= factorial(times);
}
}
return ans;
}
let arr = [1, 2, 2, 3, 3];
let N = arr.length;
document.write(UtilCountDerangements(arr, N));
</script>
|
Time Complexity: O(N * 2N)
Auxiliary Space: O(2N)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...