[leetcode]105. Construct Binary Tree from Preorder and Inorder Traversal

本文介绍如何利用先序遍历和中序遍历构建二叉树的方法。通过分析遍历序列的特点,采用递归方式实现二叉树的构建,并提供了一段C++实现代码。

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

题目链接:https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/#/description

Given preorder and inorder traversal of a tree, construct the binary tree.

Note:
You may assume that duplicates do not exist in the tree.

 1)根据先序遍历序列和中序遍历序列构建二叉树

假定已知二叉树如下:

        ___7___
       /     \
    10        2
   /   \      /
  4    3      8
        \    /
         1  11

那么它的先序遍历和中序遍历的结果如下:

preorder = {7,10,4,3,1,2,8,11}
inorder = {4,10,3,1,7,11,8,2}

      需要关注的几个要点:

1)先序遍历的第一个结点总是根结点。如上图中的二叉树,根结点为7,也是先序遍历的第一个值。先序遍历时父亲结点总是在孩子结点之前遍历。

2)可以观察到在中序遍历中,7是第4个值(从0开始算起)。由于中序遍历顺序为:左子树,根结点,右子树。所以7左边的{4,10,3,1} 这四个结点属于左子树,而根结点7右边的{11,8,2}属于右子树。

3)可以从上面的结论很轻松的得到递归式。在构建了根结点7后,我们可以根据中序遍历{41031} 和{11,8,2}分别构建它的左子树和右子树。我们同时需要相应的先序遍历结果用于发现规律。我们可以由先序遍历知道左右子树的先序遍历分别是{10,4, 3, 1}和{2, 8, 11}。左右子树也分别为二叉树,由此可以递归来解决问题。

4)关于如何得到根结点在中序遍历中的位置问题还没有细讲,如果使用线性扫描查找位置,则每次查找需要O(N)的时间,如果二叉树平衡的话,则整个算法需要O(NlgN)的时间。如果二叉树不平衡,则最坏情况需要O(N^2)时间。为了提高效率,我们可以考虑使用哈希表来存储与查找根结点在中序遍历中的位置,每次查找只需要O(1)的时间,这样构建整棵树只需要O(N)的时间。 这里为了方便,只是用了一个数组用于标记位置,要是用哈希表也会很方便。需要注意的是,这里的二叉树结点值不能有相同的值。


class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return create(preorder,inorder,0,preorder.size()-1,0,inorder.size()-1);
    }

    TreeNode* create(vector<int>& preorder,vector<int>& inorder,int ps,int pe,int is,int ie)
    {
        if(ps>pe)
            return nullptr;
        TreeNode* node=new TreeNode(preorder[ps]);
        int pos;
        for(int i=is;i<=ie;i++)
        {
            if(inorder[i]==node->val)
            {
                pos=i;
                break;
            }
        }
        node->left=create(preorder,inorder,ps+1,ps+pos-is,is,pos-1);
        node->right=create(preorder,inorder,pe-ie+pos+1,pe,pos+1,ie);
        return node;
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值