leetcode95--树

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, so  newroot->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;
        }
    };
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值