Given a positive number n, find the total number of ways in which n hats can be returned to n people such that no hat makes it back to its owner.

This problem is known as the hat–check problem and can be solved by counting the number !n of derangements of an n–element set. A derangement is a permutation of a set’s elements, such that no element appears in its original position.

 
For example,

Input:  2–hat set [h1, h2]
 
Output: The total number of derangements !2 is 1
 
[h2, h1]
 
 
Input:  3–hat set [h1, h2, h3]
 
Output: The total number of derangements !3 is 2
 
[h3, h1, h2]
[h2, h3, h1]
 
 
Input:  4–hat set [h1, h2, h3, h4]
 
Output: The total number of derangements !4 is 9
 
[h2, h1, h4, h3]
[h2, h3, h4, h1]
[h2, h4, h1, h3]
[h3, h4, h1, h2]
[h3, h1, h4, h2]
[h3, h4, h2, h1]
[h4, h1, h2, h3]
[h4, h3, h1, h2]
[h4, h3, h2, h1]

Practice this problem

The number !n of derangements of an n–hat set is defined by the following recurrence relation:

!n = (n-1) × (!(n-1) + !(n-2)), where !0 = 1 and !1 = 0.

How does this work?

Let n hats are numbered from h1 through hn, and n people are numbered from P1 through Pn. Each person may receive any of the n−1 hats that is not their own. Suppose P1 receives hat hi. Then hi’s original owner Pi either receives P1’s hat, h1, or some other hat.

Accordingly, the problem splits into two possible cases:

  1. Pi receives a hat other than h1. This case is equivalent to solving the problem with n−1 people and n−1 hats because for each of the n−1 people besides P1, there is exactly one hat from among the remaining n−1 hats that they may not receive (for any Pj besides Pi, the unreceivable hat is hj, while for Pi it is h1).
  2. Pi receives h1. In this case, the problem reduces to n−2 people and n−2 hats.

The algorithm can be implemented as follows in C, Java, and Python:

C


Download  Run Code

Output:

The total number of derangements of a 4–element set is 9

Java


Download  Run Code

Output:

The total number of derangements of a 4–element set is 9

Python


Download  Run Code

Output:

The total number of derangements of a 4–element set is 9

The time complexity of the above solution is exponential and requires additional space for the recursion (call stack).

 
It is evident that the problem has an optimal substructure since it can be recursively broken down into smaller subproblems. It also exhibits overlapping subproblems since the same subproblem is solved over and over again. The repeated subproblems can be easily seen by drawing a recursion tree:

Hat check problem – Recursion Tree

We know that problems having optimal substructure and overlapping subproblems can be solved using dynamic programming. Following is the dynamic programming implementation in C, Java, and Python, where subproblem solutions are derived in a bottom-up manner rather than computed repeatedly. An auxiliary array is used to store solutions to the subproblems.

C


Download  Run Code

Output:

The total number of derangements of a 4–element set is 9

Java


Download  Run Code

Output:

The total number of derangements of a 4–element set is 9

Python


Download  Run Code

Output:

The total number of derangements of a 4–element set is 9

The time complexity of the above solution is O(n) and requires O(n) extra space, where n is the total number of hats.

 
References: Derangement – Wikipedia