Leetcode-106-从中序与后序遍历序列构造二叉树-c++

题目详见https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/

解题关键点:

  • 后序遍历的数组最后一个元素代表的即为根节点
  • 在中序遍历的数组中找到根节点所在的下标,然后根据其将中序遍历的数组分成左右两部分,左边部分即左子树,右边部分为右子树

又添加了些注释的代码

class Solution {
    int post_idx;	//这里使用一个全局变量记录“当前”的节点所在的位置
    unordered_map<int, int> idx_map;	//这里的是使用中序遍历建立的哈希表,idx_map[val] = idx++
public:
	// 这里返回指针,也就是我们构造的二叉树的根节点
	// in_left&in_right中的in指的是inorder,也就是中序遍历的index
    TreeNode* helper(int in_left, int in_right, vector<int>& inorder, vector<int>& postorder){
        // 如果这里没有节点构造二叉树了,就结束
        if (in_left > in_right) {
            return nullptr;
        }

        // 选择 post_idx 位置的元素作为当前子树根节点
        int root_val = postorder[post_idx];	//这里这个post_idx全局变量让人发懵,请见代码中的1234条目
        
        TreeNode* root = new TreeNode(root_val);

        // 根据 root 所在位置分成左右两棵子树
        int index = idx_map[root_val];

        // 下标减一
        // 2.现在post_idx来到了根节点前的一个节点,但是此时后序遍历是按照:左-右-根的顺序进行的。
        // 因此我们移动到根左边的结点的时候该节点实际上属于根节点的右子树。
        post_idx--;
        // 构造右子树
        // 3.因此我们先构造右子树
        root->right = helper(index + 1, in_right, inorder, postorder);
        // 构造左子树
        // 4.现在post_idx来到了根节点前去除所有右子树节点之后的第一个节点,后序遍历是按照:左-右-根的顺序进行的,此时我们跳过了根和右,因此进入左子树,注意这里左-右-根我们是从右向左处理的。
        // 因此我们移动到根左边的结点的时候该节点实际上属于根节点的右子树。
        root->left = helper(in_left, index - 1, inorder, postorder);
        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        // 从后序遍历的最后一个元素开始
        //1.最开始post_idx在postorder的结尾,
        post_idx = (int)postorder.size() - 1;

        // 建立(元素,下标)键值对的哈希表
        int idx = 0;
        for (auto& val : inorder) {
            idx_map[val] = idx++;
        }
        return helper(0, (int)inorder.size() - 1, inorder, postorder);
    }
};

如有错误 敬请指正

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值