You are given an even number numPeople representing the number of people sitting around a round table. The people are numbered from 1 to numPeople in a clockwise direction.
You need to build the minimum number of handshakes so that each person shakes the hand of someone else, and no handshakes cross. In other words, if person i shakes the hand of person j, then there is no person k such that i < k < j where person k is shaking the hand of someone else.
Return the number of possible ways of doing it.
Since the answer may be very large, return it modulo 109 + 7.
Example 1:
Input: numPeople = 2 Output: 1 Explanation: There is only one way to form a handshake between person 1 and person 2.
Example 2:
Input: numPeople = 4 Output: 2 Explanation: There are two ways to form a handshake between people: - First way: person 1 shakes the hand of person 2, and person 3 shakes the hand of person 4. - Second way: person 1 shakes the hand of person 4, and person 2 shakes the hand of person 3.
Example 3:
Input: numPeople = 6 Output: 5
Constraints:
2 <= numPeople <= 1000numPeople is even.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The core idea behind the brute force approach is to explore every single possible way people can shake hands. We check each way to see if any handshakes cross each other, and count the number of ways where the handshakes don't cross.
Here's how the algorithm would work step-by-step:
def handshakes_that_dont_cross_brute_force(number_of_people):
total_non_crossing_handshakes = 0
def is_crossing(handshake_one, handshake_two):
person_one_handshake_one, person_two_handshake_one = handshake_one
person_one_handshake_two, person_two_handshake_two = handshake_two
return (person_one_handshake_one < person_one_handshake_two < person_two_handshake_one < person_two_handshake_two) or \
(person_one_handshake_two < person_one_handshake_one < person_two_handshake_two < person_two_handshake_one)
def check_for_crossing_handshakes(all_handshakes):
for i in range(len(all_handshakes)):
for j in range(i + 1, len(all_handshakes)):
if is_crossing(all_handshakes[i], all_handshakes[j]):
return True
return False
def find_all_possible_handshakes(remaining_people, current_handshakes):
nonlocal total_non_crossing_handshakes
# Base case: If everyone has shaken hands.
if not remaining_people:
# Checks to make sure there are no crossed handshakes
if not check_for_crossing_handshakes(current_handshakes):
total_non_crossing_handshakes += 1
return
# Choose the first person in the remaining people.
first_person = remaining_people[0]
# Iterate through the remaining people to find a handshake partner.
for second_person in remaining_people[1:]:
# Create new handshake
new_handshake = (first_person, second_person)
# Create the list of people left after handshake.
remaining_after_handshake = remaining_people[1:].copy()
remaining_after_handshake.remove(second_person)
# Recursively find handshakes with reduced list of people
find_all_possible_handshakes(
remaining_after_handshake,
current_handshakes + [new_handshake],
)
# Start the recursion with all people and an empty list of handshakes.
all_people = list(range(number_of_people))
# Begin by determining the base handshake combinations
find_all_possible_handshakes(all_people, [])
return total_non_crossing_handshakesThe key to solving this problem efficiently is to recognize a pattern that allows us to break down the problem into smaller, self-similar subproblems. We use a clever idea involving arranging things in a specific order and calculating the number of ways to do it without any overlaps.
Here's how the algorithm would work step-by-step:
def number_of_handshakes_that_dont_cross(number_of_people):
catalan_numbers = [0] * (number_of_people // 2 + 1)
catalan_numbers[0] = 1
# Base case: 0 people can shake hands in 1 way
for number_of_pairs in range(1, number_of_people // 2 + 1):
for j in range(number_of_pairs):
# Summing products of smaller subproblems.
catalan_numbers[number_of_pairs] += catalan_numbers[j] * catalan_numbers[number_of_pairs - 1 - j]
# The nth Catalan number gives the answer
return catalan_numbers[number_of_people // 2]| Case | How to Handle |
|---|---|
| Zero people (N=0) | Return 1, as there is one way to arrange no handshakes. |
| One person (N=1) | Return 1, as with one person, there are no handshakes to calculate. |
| Large N leading to potential integer overflow | Use a data type that can accommodate large numbers (e.g., long in Java/C++, arbitrary-precision integers in Python). |
| Odd number of people | Return 0, since it is impossible to have each person shake hands if there is an odd number of people. |
| N close to maximum integer limit | Ensure the data type chosen has sufficient range to calculate Catalan numbers for the given input, preventing overflow. |
| Negative N | Throw an IllegalArgumentException or return an error value indicating invalid input. |
| Non-integer input for N | Cast input to the appropriate integer type, or throw an error if the input cannot be reasonably converted. |
| Recursive implementation leading to stack overflow with large N | Convert the recursive solution to an iterative dynamic programming solution to avoid stack overflow. |