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

这篇博客详细介绍了如何根据一棵树的前序遍历与中序遍历序列来构造二叉树。通过手动构造步骤解析了前序和中序遍历的关系,并给出了C++代码实现,展示了深度优先搜索(DFS)在构建二叉树过程中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

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

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

例如,给出

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

返回如下的二叉树:

    3
   / \
  9  20
     /  \
    15   7

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

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

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

在这里插入图片描述首先要熟悉如何“手动”构造:
1.在中序中找到前序的第1个字母F:ACBDHEMG。F左边的点ACBD必然在F的左子树上,F右边的点HEMG必然在右子树上。图示如下:
在这里插入图片描述

2.在中序中找到前序的第2个字母C,C在左子树ACBD上,C必然是左子树ACBD的根,C左边的点A必然在C的左子树上,C右边的点BD必然在右子树上。图示如下:
在这里插入图片描述
3.在中序中找到前序的第3个字母A,A的左右两边无字母,即A的左右子树为空。图示同上。
4.在中序中找到前序的第4个字母D,D左边的B必然在D的左子树上,D的右边无字母,即D的右子树为空。图示如下:
在这里插入图片描述

5.在中序中找到前序的第5个字母B,B的左右两边无字母,即B的左右子树为空。图示同上。
6.在中序中找到前序的第6个字母E:HMG。E左边的点H必然在E的左子树上,E右边的点MG必然在E的右子树上。图示如下:
在这里插入图片描述7.在中序中找到前序的第7个字母H,H的左右两边无字母,即H的左右子树为空。图示同上。
8.在中序中找到前序的第8个字母G,G左边的M必然在G的左子树上,G的右边无字母,即G的右子树为空。图示如下:
在这里插入图片描述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);
    }
};


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值