题解:
与卡塔兰数 Catalan Number 有关
公式:
(dp[i] 表示当有i个数字能组成的 BST 的个数)
按照中序遍历的方式排列:左子树<根节点<右子树
n = 0 时,空树也算一种二叉搜索树,dp[0]=1;
n = 1 时,左右子树都是空树,左子树个数乘以右子树的个数, dp[0]*dp[0] = 1;
n = 2 时,1和2都可以为根,
dp[2] = dp[0] * dp[1] (1为根的情况,则左子树一定不存在,右子树可以有一个数字)
+ dp[1] * dp[0] (2为根的情况,则左子树可以有一个数字,右子树一定不存在)
n = 3 时,
dp[3] = dp[0] * dp[2] (1为根的情况,则左子树一定不存在,右子树可以有两个数字)
+ dp[1] * dp[1] (2为根的情况,则左右子树都可以各有一个数字)
+ dp[2] * dp[0] (3为根的情况,则左子树可以有两个数字,右子树一定不存在)
由此可推出上述卡特兰公式。
class Solution{
public:
int numTrees(int n){
vector<int>dp(n+1);
dp[0]=dp[1]=1;
for(int i=2;i<=n;i++){
for(int j=0;j<i;j++){
dp[i]+=dp[j]*dp[i-1-j];
}
}
return dp[n];
}
};
Unique Binary Search Trees Ⅱ
上一题是求所有二分查找树的数量,这题是把所有二分查找树的结构写出来
参考链接: 动态规划 递归
//Divide and Conquer
class Solution{
public:
vector<TreeNode*>generateTrees(int n){
if(n==0) return {};
vector<vector<TreeNode*>>dp(n+1);
dp[0] = vector<TreeNode*>{ nullptr };
// dp[1] = vector<TreeNode*>{ new TreeNode(1)};
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
for(TreeNode* leftTree : dp[j-1]){
for(TreeNode* rightTree : dp[i-j]){
TreeNode* node = new TreeNode(j);
node->left = leftTree;
node->right = clone (rightTree, j);
dp[i].push_back(node);
}
}
}
}
return dp.back();
}
private:
TreeNode* clone(TreeNode* root, int offset){
if (!root) return nullptr;
TreeNode* temp = new TreeNode(root->val+offset);
temp->left = clone(root->left,offset);
temp->right = clone(root->right,offset);
return temp;
}
};
//recursive method
class Solution {
public:
vector<TreeNode*> generateTrees(int n) {
if (!n) return{};
return generate(1, n);
}
private:
vector<TreeNode*> generate(int start, int end) {
vector<TreeNode*> res;
if (start > end) res.push_back(nullptr);
else if (start == end) res.push_back(new TreeNode(start));
else {
for (int i = start; i <= end; ++i) {
vector<TreeNode*> l = generate(start, i - 1);
vector<TreeNode*> r = generate(i + 1, end);
for(int j=0;j<l.size();++j)
for (int k = 0; k < r.size(); ++k) {
TreeNode* h = new TreeNode(i);
h->left = l[j];
h->right = r[k];
res.push_back(h);
}
}
}
return res;
}
};