1259. 不相交的握手
偶数 个人站成一个圆,总人数为 n
。每个人与除自己外的一个人握手,所以总共会有 n / 2
次握手。
将握手的人之间连线,请你返回连线不会相交的握手方案数。
由于结果可能会很大,请你返回答案 模 10^9+7
后的结果
示例
输入:n = 6
输出:5
解法:DP
思想
状态表示: f ( n ) f(n) f(n) 表示 n n n 个人时的握手方案数
当十个人时,如图所示,按照最后一个人的握手方式划分整个集合,将会划分成
- f ( 0 ) f(0) f(0) 与 f ( 8 ) f(8) f(8)
- f ( 2 ) f(2) f(2) 与 f ( 6 ) f(6) f(6)
- f ( 4 ) f(4) f(4) 与 f ( 4 ) f(4) f(4)
- f ( 6 ) f(6) f(6) 与 f ( 2 ) f(2) f(2)
- f ( 8 ) f(8) f(8) 与 f ( 0 ) f(0) f(0)
根据乘法原理及加法原理不难得出: f ( 10 ) = f ( 0 ) f ( 8 ) + f ( 2 ) f ( 6 ) + f ( 4 ) f ( 4 ) + f ( 6 ) f ( 2 ) + f ( 8 ) f ( 0 ) f(10) = f(0)f(8) + f(2)f(6) + f(4)f(4) + f(6)f(2) + f(8)f(0) f(10)=f(0)f(8)+f(2)f(6)+f(4)f(4)+f(6)f(2)+f(8)f(0)
由此可得 n n n 个人时, f ( n ) = f ( 0 ) f ( n − 2 ) + f ( 2 ) f ( n − 2 ) + . . . + f ( n − 2 ) ( 0 ) f(n) = f(0)f(n - 2) + f(2)f(n - 2) + ... + f(n - 2)(0) f(n)=f(0)f(n−2)+f(2)f(n−2)+...+f(n−2)(0),最后只要计算这一条公式就能得出正确答案。
复杂度
时间复杂度: O ( N 2 ) O(N^2) O(N2)
空间复杂度: O ( N ) O(N) O(N)
代码
class Solution {
public int numberOfWays(int n) {
int[] f = new int[n + 1];
int mod = 1000000007;
f[0] = 1;
f[1] = 1;
for (int i = 2; i <= n; i += 2) {
int cnt = 0;
for (int j = 0; j < i; j += 2) {
cnt = (int)((cnt + 1L * f[j] * f[i - j - 2]) % mod);
}
f[i] = cnt;
}
return f[n];
}
}