The "Handshakes That Don't Cross" problem asks you to determine how many valid ways people can shake hands around a round table such that no two handshakes cross each other.
Specifically, given n people (where n is always even), each person must shake hands with exactly one other person. A handshake is represented by a straight line drawn between two people sitting around the table. Handshakes are considered non-crossing if no two handshake lines intersect inside the circle.
Your goal is, for a given even n, to return the number of ways such non-crossing handshakes can be made.
Constraints:
n is even and in the range 0 ≤ n ≤ 1000Let's break down the problem conceptually:
n people can be built from solutions to smaller subproblems.n/2-th Catalan number gives the answer for n people.Let's outline the algorithm step-by-step:
n people, we want the number of non-crossing handshake pairings. For n = 0, there is 1 way (no handshakes).
k (where k is even and between 2 and n).k-2 people (between person 2 and person k-1), and one with n-k people (the rest).k of the product of the number of ways to handshake in each group.dp[i] denote the number of valid handshake pairings for i people.dp[0] = 1 (no people, one way).i: dp[i] = sum(dp[j] * dp[i-2-j]) for all even j from 0 to i-2.dp array up to n.dp[n] as the answer.n.
Let's walk through an example with n = 4:
1 * 1 = 1.1 * 1 = 1.1 + 1 = 2.
dp[4] = 2.
Brute-force Approach:
n.n+1.i up to n, we sum over roughly i/2 terms.O(n^2).O(n) for the DP array.n up to 1000.
The "Handshakes That Don't Cross" problem is a classic example of recursive combinatorics and dynamic programming. The key insight is recognizing that the problem is equivalent to computing Catalan numbers, which count the number of valid non-crossing pairings. By breaking the problem into subproblems and using a DP array, we can efficiently compute the answer for large n. This approach is elegant because it leverages mathematical properties and avoids brute-force enumeration.
class Solution:
def numberOfWays(self, num_people: int) -> int:
MOD = 10**9 + 7
n = num_people
dp = [0] * (n + 1)
dp[0] = 1
for i in range(2, n + 1, 2):
for j in range(0, i, 2):
dp[i] = (dp[i] + dp[j] * dp[i - 2 - j]) % MOD
return dp[n]
class Solution {
public:
int numberOfWays(int num_people) {
const int MOD = 1e9 + 7;
int n = num_people;
std::vector dp(n + 1, 0);
dp[0] = 1;
for (int i = 2; i <= n; i += 2) {
for (int j = 0; j <= i - 2; j += 2) {
dp[i] = (dp[i] + dp[j] * dp[i - 2 - j]) % MOD;
}
}
return (int)dp[n];
}
};
class Solution {
public int numberOfWays(int num_people) {
int MOD = 1000000007;
int n = num_people;
long[] dp = new long[n + 1];
dp[0] = 1;
for (int i = 2; i <= n; i += 2) {
for (int j = 0; j <= i - 2; j += 2) {
dp[i] = (dp[i] + dp[j] * dp[i - 2 - j]) % MOD;
}
}
return (int)dp[n];
}
}
var numberOfWays = function(num_people) {
const MOD = 1e9 + 7;
let n = num_people;
let dp = new Array(n + 1).fill(0);
dp[0] = 1;
for (let i = 2; i <= n; i += 2) {
for (let j = 0; j <= i - 2; j += 2) {
dp[i] = (dp[i] + dp[j] * dp[i - 2 - j]) % MOD;
}
}
return dp[n];
};