105、106、889从前中、中后、前后遍历构造二叉树

本文介绍了如何根据前序与中序遍历序列、中序与后序遍历序列以及前序和后序遍历序列来构造二叉树。关键在于找到根节点的位置,然后递归地构建左右子树。对于前序与中序遍历,前序的第一个元素是根节点;对于中序与后序遍历,后序的最后一个元素是根节点;对于前序和后序遍历,前序的第二个元素是左子树的根节点。
摘要由CSDN通过智能技术生成

105. 从前序与中序遍历序列构造二叉树

返回与给定的前序和后序遍历匹配的任何二叉树。
pre 和 post 遍历中的值是不同的正整数。

思路

刷到了这道题,然后想着把这类题目都总结下,这类问题的关键是从根节点的位置区别左右子树,前序遍历的preinorder[pre_start]必定是第一个根节点,然后在中序遍历中找到该节点的位置index,这样inorder[in_start, index - 1]就是左子树了,inorder[index + 1, in_end]就是右子树,找出了左右子树的范围后就可以确定左右子树的节点的数量了,再反过来定位preorder的位置即可。

  • 左子树值数量:left_size = index - in_start,preorder递归范围[pre_start + 1, pre_start + left_size],inorder递归范围[ib, index - 1]
  • 右子树值数量:right_size = in_end - index(其实不用算),直接根据上面得出的范围即可,preorder递归范围[pre_start + left_size + 1, pre_end],inorder递归范围[index + 1, in_end]

代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    unordered_map<int, int> root_idx;
    TreeNode* dfs(vector<int>& preorder, int pb, int pe, vector<int>& inorder, int ib, int ie) {
        if(pb > pe) {
            return nullptr;
        }
        //取出根节点值
        int val = preorder[pb];
        //在中序遍历中找到根节点位置
        int index = root_idx[val];
        //建树
        TreeNode* root = new TreeNode(val);
        //计算左子树值数量
        int left_size = index - ib;
        //递归确定左右子树
        root -> left = dfs(preorder, pb + 1, pb + left_size, inorder, ib, index - 1);
        root -> right = dfs(preorder, pb + left_size + 1, pe, inorder, index + 1, ie);
        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n = preorder.size();
        int idx = 0;
        for(const int& num : inorder) {
            root_idx[num] = idx++;
        }
        return dfs(preorder, 0, n - 1, inorder, 0, n - 1);
    }
};

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

根据一棵树的中序遍历与后序遍历构造二叉树。

思路

同理,后序遍历的最后一个postorder[post_end]必定是根节点,然后根据该值在中序遍历中寻找根节点位置,分为左右子树即可。需要注意的是,直接从后序倒序遍历时,会先访问到右子树的根节点,所以先构建右子树。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int post_idx;
    unordered_map<int, int> root_idx;
    TreeNode* dfs(int start, int end, vector<int>& inorder, vector<int>& postorder) {
        if(start > end) {
            return nullptr;
        }
        int index = root_idx[postorder[post_idx]];
        post_idx--;
        TreeNode* root = new TreeNode(inorder[index]);

        root -> right = dfs(index + 1, end, inorder, postorder);
        root -> left = dfs(start, index - 1, inorder, postorder);
        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        post_idx = postorder.size() - 1;
        int idx = 0;
        for(const int& num : inorder) {
            root_idx[num] = idx++;
        }
        return dfs(0, inorder.size() - 1, inorder, postorder);
    }
};

889. 根据前序和后序遍历构造二叉树

返回与给定的前序和后序遍历匹配的任何二叉树。
pre 和 post 遍历中的值是不同的正整数。

思路

可以知道preorder[pre_start + 1]必定为左子树的根节点,然后再postordered中找出该位置即可。

代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    unordered_map<int, int> post_idx;
    TreeNode* dfs(vector<int>& pre, vector<int>& post, int pre_b, int pre_e, int post_b, int post_e) {
        if(pre_b > pre_e) {
            return nullptr;
        }
        TreeNode* root = new TreeNode(pre[pre_b]);
        
    	//只有一个节点了,直接返回
        if(pre_b == pre_e) {
            return root;
        }
        //找到左子树的根节点
        int val = pre[pre_b + 1];
        //在后序遍历定位
        int index = post_idx[val];
        //计算左子树数量
        int left_size = index - post_b + 1;
        //递归左右子树
        root -> left = dfs(pre, post, pre_b + 1, pre_b + left_size, post_b, index);
        root -> right = dfs(pre, post, pre_b + left_size + 1, pre_e, index + 1, post_e - 1);
        return root;
    }
    TreeNode* constructFromPrePost(vector<int>& pre, vector<int>& post) {
        int n = post.size();
        for(int i = 0; i < n; i++) {
            post_idx[post[i]] = i;
        }
        return dfs(pre, post, 0, n -1, 0, n -1);
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值