卡塔兰数定义
f(n) = f(0)f(n-1) + f(1)f(n-2) + ... + f(n-1)f(0)
= f(k-1)f(n-k) k=1...n
以k为轴划分子问题,左边子问题的解的个数和右边子问题的解的个数是原问题以k为轴的解法的2个独立步骤,适用乘法原理
分别以1,2,。。。n为轴,是原问题的n种解法,适用加法原理。
int cantalan(int n) {
vector<int> f(n + 1);
f[0] = 1;
for (int i = 1; i <= n; i++)
for (int k = 1; k <= i; k++) //iterate the case k(1..i) as the root
f[i] += f[k - 1] * f[i - k];
return f[n];
}
应用:
1)给定n个括号,求所有合法括号组合数。
划分办法:第一个左括号分别和第k个(k=1...n)右括号结合,这样k左边有k-1个右括号(也必然有k-1个左括号,因为我们在讨论合法组合),解个数f(k-1), k右边n-k个右括号,解个数f(n-k)
或者这么理解划分:第一个括号里放k个括号(可以是从0到n - 1)对问题是一个独立且完备的划分。f(n) = f(k) f(n -k) k=0..n-1
2)连乘加括号问题
划分办法:考虑乘号而不是数,第几个乘号之前的右括号和最前面的左括号结合。
3)给定一个集合,求可以构造的所有二叉查找树的个数:
划分:分别以每个数为root