原题链接:不同的二叉搜索树
个人解法
思路:
我们可以将一棵二叉搜索树抽象为一个顶点与左右两棵子树构成,这样统计一棵搜索树能构成多少棵不同的树转换为统计其左右子树能构成的不同二叉搜索树的乘积。
既f[root] = f[root->left] * f[root->right]
,注意如果递归计算的话会TLE,原因是有一些值已经算过了,重复计算会使得计算量增大,故可以用记忆化搜索
时间复杂度: O ( n 2 ) O(n^2) O(n2)
代码:
class Solution {
public:
unordered_map<int, int> st;
int numTrees(int n) {
if(n == 0 || n == 1) return 1;
if(st.count(n)) return st[n];
int res = 0;
for(int i = 1;i <= n;i ++) {
res += numTrees(i - 1) * numTrees(n - i);
}
st[n] = res;
return res;
}
};
更好的解法
思路:
动态规划
实际上就是上述思想的非递归形式
状态表示:f[i]表示长度为i的序列构成的二叉搜索树的个数
状态转移:f[i] = f[i - 1] * f[n - i]
时间复杂度: O ( n 2 ) O(n^2) O(n2)
代码:
class Solution {
public:
int numTrees(int n) {
vector<int> f(n + 1, 0);
f[0] = 1, f[1] = 1;
for(int i = 2;i <= n;i ++) {
for(int j = 1; j <= i;j ++) {
f[i] += f[j - 1] * f[i - j];
}
}
return f[n];
}
};