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

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。

示例 1:

输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

提示:

1 <= inorder.length <= 3000
postorder.length == inorder.length
-3000 <= inorder[i], postorder[i] <= 3000
inorder 和 postorder 都由 不同 的值组成
postorder 中每一个值都在 inorder 中
inorder 保证是树的中序遍历
postorder 保证是树的后序遍历

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

解析: 

这道题的题意是非常清晰的,是我们在学习二叉树的时候经常碰到的那种,给你前序、中序、后序遍历中的两者,让你构造原树或者另外一种遍历的结果。

题中给与我们的是树的中序遍历以及后序遍历

首先我们要理清这两者的大概思路是什么:

中序遍历的大概思路是:

1.遍历左子树

2.输出当前结点

3.遍历右子树

后序遍历的大概思路是:

1.遍历左子树

2.遍历右子树

3.输出当前结点

所以,中序遍历的结果分布是这样的:

左子树根节点右子树

而后序遍历的结果分布是这样的:

左子树右子树根节点

可以看出,通过后序遍历,我们非常容易找到树的根节点以及右子树的根节点

而在中序遍历中,以根节点为中心,又很清楚的将左右子树完美的分割开来

所以我们大致的代码思路可以为:

1.根据后序遍历确定根节点

2.创建根节点

3.在中序遍历中将左右子树分割开来

4.进入右子树重复上述操作

5.进入右子树重复上述操作

需要注意的一点是,由于后序遍历的结果分布,我们必须先遍历右子树,而后才可以遍历左子树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) 
 *      : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    int idx;
    unordered_map<int, int> idx_map;
public:
    TreeNode* creating(int left, int right, 
        vector<int>& inorder, vector<int>& postorder) {
        //判断是该子树是否为空
        if (left > right) {
            return nullptr;
        }
        
        //取出根节点的值
        int val = postorder[idx];
        TreeNode* root = new TreeNode(val);

        //确认分割位置
        int split = idx_map[val];
        
        //寻找后序遍历中的下一个元素,类的成员变量
        idx--;
        //在中序遍历中划出右子树部分,在它的基础上建立右子树
        root->right = creating(split + 1, right, inorder, postorder);
        //在中序遍历中划出左子树部分,在它的基础上建立左子树
        root->left = creating(left, split - 1, inorder, postorder);
        
        return root;
    }

    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        idx = inorder.size() - 1;

        int cnt = 0;
        //将中序遍历中元素与其下标对应存储。
        for (int& i : inorder) {
            idx_map[i] = cnt++;
        }

        return creating(0, idx, inorder, postorder);
    }
};
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云雷屯176

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值