Problem#
You are given an even number of people numPeople
that stand around a circle and each person shakes hands with someone else so that there are
numPeople / 2
handshakes total.
Return the number of ways these handshakes could occur such that none of the handshakes cross .
Since the answer could be very large, return it modulo 109 + 7
.
Examples#
Example 1:
1
2
3
4

Input: numPeople = 4
Output: 2
Explanation: There are two ways to do it, the first way is [( 1 , 2 ),( 3 , 4 )] and the second one is [( 2 , 3 ),( 4 , 1 )].
Example 2:
1
2
3

Input: numPeople = 6
Output: 5
Constraints:
2 <= numPeople <= 1000
numPeople
is even.
Solution#
Method 1 – Dynamic Programming (Catalan Numbers)#
Intuition#
The problem asks for the number of ways to pair up people in a circle such that no handshakes cross. This is a classic application of the Catalan numbers, which count the number of non-crossing handshakes (or valid parenthesis sequences, binary trees, etc.).
Approach#
Let n = numPeople / 2
. The answer is the nth Catalan number.
Use dynamic programming to compute Catalan numbers:
dp[0] = 1
(base case: 0 pairs)
For each i
from 1 to n
, compute dp[i] = sum_{j=0}^{i-1} dp[j] * dp[i-1-j]
.
Take modulo 10^9 + 7
at each step.
Return dp[n]
as the answer.
Code#
Cpp
Go
Java
Kotlin
Python
Rust
Typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public :
int numberOfWays(int numPeople) {
int n = numPeople / 2 , mod = 1e9 + 7 ;
vector< long long > dp(n+ 1 , 0 );
dp[0 ] = 1 ;
for (int i = 1 ; i <= n; ++ i) {
for (int j = 0 ; j < i; ++ j) {
dp[i] = (dp[i] + dp[j] * dp[i- 1 - j]) % mod;
}
}
return dp[n];
}
};
1
2
3
4
5
6
7
8
9
10
11
func numberOfWays (numPeople int ) int {
n , mod := numPeople / 2 , int(1e9 + 7 )
dp := make([]int , n + 1 )
dp [0 ] = 1
for i := 1 ; i <= n ; i ++ {
for j := 0 ; j < i ; j ++ {
dp [i ] = (dp [i ] + dp [j ]* dp [i - 1 - j ]) % mod
}
}
return dp [n ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public int numberOfWays (int numPeople) {
int n = numPeople / 2, mod = 1_000_000_007;
long [] dp = new long [ n+ 1] ;
dp[ 0] = 1;
for (int i = 1; i <= n; ++ i) {
for (int j = 0; j < i; ++ j) {
dp[ i] = (dp[ i] + dp[ j] * dp[ i- 1- j] ) % mod;
}
}
return (int )dp[ n] ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
fun numberOfWays (numPeople: Int): Int {
val n = numPeople / 2
val mod = 1 _000_000_007
val dp = LongArray(n+1 )
dp[0 ] = 1L
for (i in 1. .n) {
for (j in 0 until i) {
dp[i] = (dp[i] + dp[j] * dp[i-1 -j]) % mod
}
}
return dp[n].toInt()
}
}
1
2
3
4
5
6
7
8
9
class Solution :
def numberOfWays (self, numPeople: int) -> int:
n, mod = numPeople // 2 , 10 ** 9 + 7
dp: list[int] = [0 ] * (n+ 1 )
dp[0 ] = 1
for i in range(1 , n+ 1 ):
for j in range(i):
dp[i] = (dp[i] + dp[j] * dp[i- 1 - j]) % mod
return dp[n]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct Solution ;
impl Solution {
pub fn number_of_ways (num_people: i32 ) -> i32 {
let n = (num_people / 2 ) as usize ;
let m = 1_000_000_007 ;
let mut dp = vec! [0 i64 ; n+ 1 ];
dp[0 ] = 1 ;
for i in 1 ..= n {
for j in 0 .. i {
dp[i] = (dp[i] + dp[j] * dp[i- 1 - j]) % m;
}
}
dp[n] as i32
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
numberOfWays (numPeople : number ): number {
const n = numPeople / 2 , mod = 1 e9 + 7 ;
const dp : number [] = Array(n + 1 ).fill (0 );
dp [0 ] = 1 ;
for (let i = 1 ; i <= n ; ++ i ) {
for (let j = 0 ; j < i ; ++ j ) {
dp [i ] = (dp [i ] + dp [j ] * dp [i - 1 - j ]) % mod ;
}
}
return dp [n ];
}
}
Complexity#
⏰ Time complexity: O(n^2)
, since for each i up to n, we sum over all j < i.
🧺 Space complexity: O(n)
, for the dp array.