原题:
原题:
Given an integer n, generate all structurally unique BST's (binary search trees) that store values 1...n.
For example,
Given n = 3, your program should return all 5 unique BST's shown below.
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
解题思路:
这个题的P97简单版可以用DP解决,可以选择先把P97做了,然后做这题,还是纠结了挺久,主要是在不知道有没有更快的方法的情况下,不敢轻易开码,最后还是选择和P97一样的思路,这里我还是用了DP,用来减少一些花销。
代码如下(思路主要见注释):
// 是一道好题,但这题一直不太敢写,因为我一直觉得会有很简单的方法
// 但是事实证明好像大家都没有想到好的解法
// 那样的话就用上一题的思路解决它吧,我们还是用到了DP
// 不过DP只有在左侧可以复用节点,但是在右侧我们不可以复用结点
// 右侧我们要进行深拷贝,深拷贝可以用递归进行
// ==》DP的时间复杂度和空间复杂度都是比直接递归做要节约挺多的
// 最终的时间复杂度有点太高了,比较难计算
class Solution {
public:
TreeNode* copyTree(TreeNode* root, int inc){
// 递归地深拷贝这棵树,注意要加上偏移量
if (root == NULL) return NULL;
TreeNode* newRoot = new TreeNode(root->val + inc);
newRoot->left = copyTree(root->left, inc);
newRoot->right = copyTree(root->right, inc);
return newRoot;
}
vector<TreeNode*> generateTrees(int n) {
const int size = n;
vector<vector<TreeNode*>> dp(size+1);
if(n == 0)return dp[0];
dp[0].push_back(NULL);
for (int i = 1; i <= n; ++i)
{
// 自底向上构建dp
for (int j = 1; j <= i; ++j)
{
// 选择一个作为根节点
int leftSize = j - 1;
int rightSize = i - j;
for (int k = 0; k < dp[leftSize].size(); ++k)
{
// 左侧的dp[leftSize].size()种可能
for (int l = 0; l < dp[rightSize].size(); ++l)
{
// 右侧的dp[rightSize].size()种可能,注意这棵树里的节点全都要加上j
TreeNode *root = new TreeNode(j);
root->left = dp[leftSize][k];
// 左侧树可以不用更改
root->right = copyTree(dp[rightSize][l], j);
// 我们可以直接拷贝,由于rightSize+j=i
// 所以每次i,这颗右边的树都是不同的,每次都要深拷贝
dp[i].push_back(root);
// 最后把候选解放进去
}
}
}
}
return dp[n];
}
};