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

题目描述

题目链接:leetcode 从前序与中序遍历序列构造二叉树
根据一棵树的前序遍历与中序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

返回如下的二叉树:

    3
   / \
  9  20
     /  \
    15   7

根据前序和中序遍历构造二叉树的方法

     前序遍历:“根左右”(先访问根再访问左儿子最后访问右儿子)
     中序遍历:“左根右”(先访问左儿子再访问根最后访问右儿子)

     以下图的二叉树为例:
 前序遍历为:FCADBEHGM
 中序遍历为:ACBDFHEMG

leetcode 105. 从前序与中序遍历序列构造二叉树_第1张图片首先要熟悉如何“手动”构造:
1.在中序中找到前序的第1个字母F:ACBDHEMG。F左边的点ACBD必然在F的左子树上,F右边的点HEMG必然在右子树上。图示如下:
leetcode 105. 从前序与中序遍历序列构造二叉树_第2张图片

2.在中序中找到前序的第2个字母C,C在左子树ACBD上,C必然是左子树ACBD的根,C左边的点A必然在C的左子树上,C右边的点BD必然在右子树上。图示如下:
leetcode 105. 从前序与中序遍历序列构造二叉树_第3张图片
3.在中序中找到前序的第3个字母A,A的左右两边无字母,即A的左右子树为空。图示同上。
4.在中序中找到前序的第4个字母D,D左边的B必然在D的左子树上,D的右边无字母,即D的右子树为空。图示如下:
leetcode 105. 从前序与中序遍历序列构造二叉树_第4张图片

5.在中序中找到前序的第5个字母B,B的左右两边无字母,即B的左右子树为空。图示同上。
6.在中序中找到前序的第6个字母E:HMG。E左边的点H必然在E的左子树上,E右边的点MG必然在E的右子树上。图示如下:
leetcode 105. 从前序与中序遍历序列构造二叉树_第5张图片7.在中序中找到前序的第7个字母H,H的左右两边无字母,即H的左右子树为空。图示同上。
8.在中序中找到前序的第8个字母G,G左边的M必然在G的左子树上,G的右边无字母,即G的右子树为空。图示如下:
leetcode 105. 从前序与中序遍历序列构造二叉树_第6张图片9.在中序中找到前序的第9个字母M,M的左右两边无字母,即M的左右子树为空。图示同上。

根据“手动”构造的步骤,很容易得到用程序构造的具体做法:
(1)遍历前序中的节点,选当前遍历到的节点作为“当前二叉树”的根,用“当前节点”将后序划分为左右子树两部分。
(2)分别在左右子树中重复(1)即可。

C++代码


class Solution {
public:
    /**
     dfs方法参数说明:
     preorder:前序数组
     inorder:后序数组
     l:后序数组的区间左端点
     r:后序数组的区间右端点
     step:用于遍历前序数组的“当前节点”preorder[step]
     非常关键的一点就是:
     每次调用dfs,在后序中找到前序中的“当前节点”时,都要让step自增
     因为只要将“当前节点”设为根,下一步就要遍历前序中的下一个节点
    */
    TreeNode* dfs(vector<int>& preorder, vector<int>& inorder,int l,int r,int & step){

        TreeNode *root=nullptr;  //将当前子树的根设为空
        
        for(int i=l;i<=r;i++){
         
            if(inorder[i]==preorder[step]){ //如果在后序中找到前序中的“当前节点”
                root=new TreeNode;
                root->val=inorder[i];  //选“当前节点”作为“当前子树”的根
                step++; 
                //递归构造左右子树  
                root->left=dfs(preorder,inorder,l,i-1,step);
                root->right=dfs(preorder,inorder,i+1,r,step);
                break;
            }
        }


        return root;
    }



    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
    int l=0,r=preorder.size()-1,step=0;
    return dfs(preorder,inorder,l,r,step);
    }
};


你可能感兴趣的:(算法刷题,二叉树,前序遍历,后序遍历)