给定一个整数 n,求以 1 … n 为节点组成的二叉搜索树有多少种?
示例:
输入: 3
输出: 5
解释:
给定 n = 3, 一共有 5 种不同结构的二叉搜索树:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
这里解题思路是:假设,现在有n个数,那么,理论上讲,每个数字都可以作为这个树的树根。
解释一下上面那些树产生的过程:
- n=0 表示,有0个点,那么,可以组成的二叉查找树就一个,那就是空树
- n=1表示,有1个点,那么,可以组成的二叉查找树就一个,那就是根节点为1,左右子树均为空子树
- n=2表示,有2个点,那么,可以组成的二叉查找数就两个,假设,点集合为[0,1,2](这里的第一个0表示空点,就是空子树)那么,0不能做根,如果1做根,那么左子树为0,右子树就是2(看出来了吗刚好是从1处截断了),如果2做根,那么左子树为[0,1],右子树为空子树(刚好从2处截断了(递推为f(3)=f(0)(2)+f(1)f(1)+f(2)f(0)))。
- 以此类推,假设n=t,那么表示,有t个点,那么假设让第x个点做根,那么,左子树为[0,……,t-1],右子树为[t+1,……,n],那么,最终的答案是 f(t) * f(n-t-1)这里f(a)表示如果有a个点,那么可以组成的树的个数(毕竟我们是在处理这些数字之前,他们就有顺序了,比如,[0,1,2]
class Solution {
public:
int numTrees(int n) {
vector<int> vi;
if (n==0) return 1;
if (n==1) return 1;
vi.push_back(1);
vi.push_back(1);
for (int i = 2; i <= n; ++i) {
//这里计算 n=i的情况
int tmp=0;
for (int j = 0; j < i; ++j) {
tmp += vi[j]*vi[i-j-1];
}
vi.push_back(tmp);
}
return vi.back();
}
};