剑指 Offer 07. 重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。

假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
示例1
在这里插入图片描述

Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]

示例 2:

Input: preorder = [-1], inorder = [-1]
Output: [-1]

题解

在这里插入图片描述
我们这道题可以从前序遍历当中知道构建二叉树根节点的值,在中序遍历当中去找到这个值对应的下标我们可以用hash表,使得查找到时间复杂度为O(1)的 ;

具体步骤

  • 初始化一个hash表,unordered_map<int,int> pos,将中序遍历的val作为map中的key,坐标就是value : for(int i = 0 ; i < inorder.size() ; i ++) pos[inorder[i]] = i ;
  • 假前序遍历的左边界 pl , 右边界 pr ,中序遍历的左边界 il, 中序遍历的右边界 ir,每次都能从2个区间确定一个点,所以每次都更新区间!
  • 通过preorder[pl]确定树的根节点,然后通过hash表找到根节点在中序遍历的位置
auto root = new TreeNode(preorder[pl]) ;
int k = pos[root -> val] ;
  • 找到根节点的位置,就能更新区间的范围,如下
    在这里插入图片描述
    然后通过新的区间递归得出左子树的根,右子树的根,最后返回root
class Solution {
public:
    unordered_map<int,int> pos ; //hash表用来记录中序遍历当中每个点的位置!
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        for(int i = 0 ; i < inorder.size() ; i ++) pos[inorder[i]] = i ; //记录一下每个点的下标
        return build(preorder,inorder,0,preorder.size() - 1 , 0 ,inorder.size() - 1) ; // 递归构建树
    }
    TreeNode* build(vector<int>& preorder,vector<int>& inorder, int pl,int pr,int il,int ir){
        if(pl > pr) return nullptr ;
        auto root = new TreeNode(preorder[pl]) ;
        int k = pos[root -> val] ;
        root -> left = build(preorder,inorder,pl + 1 ,pl + k - il ,il,k-1) ;
        root -> right = build(preorder,inorder,pl + k - il + 1 ,pr ,k+1,ir) ;
        return root ;
    }
};
posted @ 2022-01-23 20:35  爪洼ing  阅读(17)  评论(0编辑  收藏  举报