95
Given an integer n, generate all structurally unique BST's (binary search trees) that store values 1 ... n.
Example:
Input: 3 Output: [ [1,null,3,2], [3,2,null,1], [3,1,null,null,2], [2,1,3], [1,null,2,null,3] ] Explanation: The above output corresponds to the 5 unique BST's shown below: 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3
//解题思路:
//想知道用第i个数来构成多少个BST,那么可以用动态规划来做//res存储的是包含前i-1个数字包含的所有树,想知道包含i这个数字可以构成多少BST,有两点需要考虑
//1:当充当根节点的时候,前i-1个数充当他的做孩子就可以了,那么此时只需要便利res(存储的都是根节点root【1~res.size()),然后嫁给他们都指向Treenode(i)Treenode的初始化--需要clone函数,是因为接下来第二种情况同样需要没有加入Treenode(i)这个结点的原树结构oldroot,所以clone原树,把clone的树作为root(i)的左孩子,然后把这些改变之后的树根结点root放进临时的res结构tmp(tmp之后存完所有数据再来更新res,是因为每一次计算包含数字n的时候,res里面的所有树,包括以1,2,3,4...为根节点的树都要包含数字n,所以每一次计算,都有对res进行更新,不仅仅是有内容,还有数量的递增,res(i)和res(i-1)是完全不同的)
//2:当i不充当根节点,那么这个Treenode(i)就只能充当每棵树的右孩子,而原树的右孩子要成为Treenode(i)的左孩子,其中这个Treenode(i)不仅可以作为oldroot的左孩子,还可以作为root->right的右孩子,也就是说只要root->right不为空,那么就可以一直循环下去,这就是为什么说要对每一棵树进行多次操作的原因(每一次更新不适用对相同的树clone的原因可能在于空间开销太大,这不同于第一种情况。第一种情况只对res中的树操作一次,所以clone一下没问题,而第二种是要对每一棵树进行多次操作,这样不仅浪费时间也浪费空间)对于clone的运用,在第二种情况里有这样一种运用,当我们完成Treenode(i)接到root右孩子并且把原来的右孩子接到它的左侧这些操作之后,我们clone这个完成的树,并把这棵树放进tmp中,而原来那个用来进行下一次的右孩子移动操作,最简单的还原就是让原来的右孩子再指回原根节点,然后tmpold=tmpold->right这种经典操作(解读:tmpold存的是地址,开始的时候是root的地址Treenode *tmpold=root,然后覆盖他所存的地址信息tmp->right)
//第二种成立的条件是存在右孩子,若没有的话就直接接上,至于为什么还要colne一次,并恢复原树结构,有点不太清楚??????
//然后就对res更新res=tmp,返回res就ok了
The basic idea is that we can construct the result of n node tree just from the result of n-1 node tree.
Here's how we do it: only 2 conditions: 1) The nth node is the new root, sonewroot->left = oldroot;
2) the nth node is not root, we traverse the old tree, every time the node in the old tree has a right child, we can perform:
old node->right = nth node, nth node ->left = right child;
and when we reach the end of the tree, don't forget we can also add the nth node here.
One thing to notice is that every time we push a TreeNode in our result, I push the clone version of the root, and I recover what I do to the old node immediately. This is because you may use the old tree for several times.
class Solution {
public:
TreeNode* clone(TreeNode* root){
if(root == nullptr)
return nullptr;
TreeNode* newroot = new TreeNode(root->val);
newroot->left = clone(root->left);
newroot->right = clone(root->right);
return newroot;
}
vector<TreeNode *> generateTrees(int n) {
vector<TreeNode *> res(1,nullptr);
for(int i = 1; i <= n; i++){
vector<TreeNode *> tmp;
for(int j = 0; j<res.size();j++){
TreeNode* oldroot = res[j];
TreeNode* root = new TreeNode(i);
TreeNode* target = clone(oldroot);
root->left = target;
tmp.push_back(root);
if(oldroot!=nullptr){
TreeNode* tmpold = oldroot;
while(tmpold->right!=nullptr){
TreeNode* nonroot = new TreeNode(i);
TreeNode *tright = tmpold->right;
tmpold->right = nonroot;
nonroot->left = tright;
TreeNode *target = clone(oldroot);
tmp.push_back(target);
tmpold->right = tright;
tmpold = tmpold->right;
}
tmpold->right = new TreeNode(i);
TreeNode *target = clone(oldroot);
tmp.push_back(target);
tmpold->right = nullptr;
}
}
res=tmp;
}
return res;
}
};