106.从中序与后序遍历序列构造二叉树

这道题目确实不简单,但是如果能想通 其实也很简单

搞清楚中序和后序

首先我们要明白中序 和 后序的区别 中序是 左中又   后序则是左右中

按照这个逻辑  我们可以知道  后序数组的后面都是父节点

int val = postorder.back();
        auto *node = new TreeNode(val);
        if(postorder.size()==1)return node;

切割中序

根据后序中的父节点 我们切割中序 得出了两个中序数组 

这两个中序数组 对应了这个父节点的左子树 和 右子树

 //切割中序数组
        vector<int> inorderleft(inorder.begin(),it);
        vector<int> inorderright(it+1,inorder.end());

其实这里很好简单的想到 问题是怎么去切割 后序 从而将后序分为两个部分

首先在我们切割中序后 我们首先需要弹出后序的最后一个 因为我们已经使用了他

postorder.resize(postorder.size()-1);

然后就是关键的一步

切割后序

我们观察到 中序后序 他们的开头都是左 这就意味着 我们剔除了最后一个父节点  切割中序

那么中序中的左子树尺寸不就是对应了后序的左子树尺寸吗

所以我们切割后序 按照 中序的尺寸大小直接切割就完事了

  vector<int> postorderleft(postorder.begin(),postorder.begin()+(int)inorderleft.size());
        vector<int> postorderright(postorder.begin()+(int)inorderleft.size(),postorder.end());

其实还有一部很重要 就是我们需要终止递归结束条件

我们选择递归到叶子节点选择return

完整代码

class Solution {
public:
    TreeNode* createTree(vector<int>& inorder, vector<int>& postorder){
        //结束递归条件
        if(postorder.empty())return nullptr;
        //从后序数组最后一个构建头节点
        int val = postorder.back();
        auto *node = new TreeNode(val);
        if(postorder.size()==1)return node;
        auto it = find(inorder.begin(),inorder.end(),val);
        //切割中序数组
        vector<int> inorderleft(inorder.begin(),it);
        vector<int> inorderright(it+1,inorder.end());
        //切割后序数组
        postorder.resize(postorder.size()-1);
        vector<int> postorderleft(postorder.begin(),postorder.begin()+(int)inorderleft.size());
        vector<int> postorderright(postorder.begin()+(int)inorderleft.size(),postorder.end());
        node->left = createTree(inorderleft,postorderleft);
        node->right = createTree(inorderright,postorderright);
        return node;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if (inorder.size() == 0 || postorder.size() == 0) return nullptr;
    return createTree( inorder,  postorder);
    }
};

类似题目还有

https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/

一并附上代码很简单

class Solution {
public:
    TreeNode* createTree(vector<int>& preorder, vector<int>& inorder){
        //分析两种遍历方法的区别 中左右 左中右
        if(preorder.size()==1)return new TreeNode(preorder.front());
        if(inorder.empty() || preorder.empty()) return nullptr;
        int val = preorder.front();
        TreeNode *node = new TreeNode(val);
        preorder.erase(preorder.begin());
        //切割中序
        auto it = find(inorder.begin(),inorder.end(),val);
        vector<int> inorderleft(inorder.begin(),it);
        vector<int> inorderright(it+1,inorder.end());
        //切割前序
        vector<int> preorderleft(preorder.begin(),preorder.begin()+(int)inorderleft.size());
        vector<int> preorderright(preorder.begin()+(int)inorderleft.size(),preorder.end());

        node->left= createTree(preorderleft,inorderleft);
        node->right= createTree(preorderright,inorderright);
        return node;

    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if(inorder.empty() || preorder.empty()) return nullptr;
        return createTree( preorder,  inorder);
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值