力扣第106题 中后序 构造二叉树 c++ 数据结构必学系列

题目

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

中等

相关标签

  数组  哈希表  分治  二叉树

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。

示例 1:

输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]

示例 2:

输入:inorder = [-1], postorder = [-1]
输出:[-1]

提示:

  • 1 <= inorder.length <= 3000
  • postorder.length == inorder.length
  • -3000 <= inorder[i], postorder[i] <= 3000
  • inorder 和 postorder 都由 不同 的值组成
  • postorder 中每一个值都在 inorder 中
  • inorder 保证是树的中序遍历
  • postorder 保证是树的后序遍历

思路和解题方法

首先,定义了一个私有函数traver,用于递归构建二叉树。函数的参数包括前序遍历结果数组、中序遍历结果数组以及它们的起始和终止位置。

在函数内部,首先判断递归终止条件,即当前前序遍历区间只有一个元素时,直接创建节点并返回。

然后,通过前序遍历结果数组的第一个元素确定根节点的值,并创建根节点。

接下来,通过在中序遍历结果数组中查找根节点的值,确定中序遍历结果数组的切割点(即根节点的位置)。

将中序遍历结果数组切割成左右两个区间,分别对应左子树和右子树。

同时,根据中序遍历结果数组的切割点计算出前序遍历结果数组的左右两个区间。

然后,递归调用traver函数分别构建左子树和右子树,并将其返回的结果分别赋值给根节点的左子节点和右子节点。

最后,在主函数buildTree中判断输入的前序遍历和中序遍历数组是否为空,若为空则直接返回空指针。

调用traver函数,并传入前序遍历和中序遍历数组的起始和终止位置,得到构建好的二叉树,最后返回根节点。

复杂度

        时间复杂度:

                O(n)

时间复杂度:O(n),其中 nnn 是树中的节点个数。

        空间复杂度

                O(n)

空间复杂度:O(n)。我们需要使用 O(n) 的空间存储哈希表,以及 O(h)其中 h 是树的高度)的空间表示递归时栈空间。这里 h<n,所以总空间复杂度为 O(n)。

c++ 代码

class Solution {
public:
    // traver函数根据中序遍历和后序遍历构建二叉树
    TreeNode *traver(vector<int> &in , vector<int>&po)
    {
        // 如果后序遍历数组为空,说明当前子树为空,返回空指针
        if(po.size()==0) return NULL;
        
        // 后序遍历的最后一个元素是当前子树的根节点值
        int rootval = po[po.size()-1];
        
        // 使用根节点值创建新的二叉树节点
        TreeNode *root = new TreeNode(rootval);
        
        // 如果后序遍历数组只有一个元素,说明当前子树只有根节点,直接返回
        if(po.size() == 1)return root;
        
        // 在中序遍历数组中找到根节点值的位置
        int index;
        for(index=0;index<in.size();index++)
        {
            if(in[index]==rootval) break;
        }
        
        // 根据中序遍历和后序遍历的特点,将中序遍历数组和后序遍历数组分别分割为左子树和右子树的序列
        vector<int> ltin(in.begin(),in.begin()+index);  // 左子树的中序遍历序列
        vector<int> rtin(in.begin()+index+1,in.end());  // 右子树的中序遍历序列
        
        // 后序遍历数组当前根节点值减1,因为根节点值已经在当前子树中使用了
        po.resize(po.size()-1);
        
        // 根据左子树的中序遍历序列和后序遍历序列构建左子树
        vector<int> ltpo(po.begin(),po.begin()+ltin.size());  // 左子树的后序遍历序列
        vector<int> rtpo(po.begin()+ltin.size(),po.end());  // 右子树的后序遍历序列
        
        // 递归构建左子树和右子树,并将它们连接到根节点上
        root->left = traver(ltin,ltpo);
        root->right = traver(rtin,rtpo);
        
        // 返回根节点
        return root;
    }
    
    // buildTree函数是构建二叉树的入口,它调用traver函数来完成构建过程
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        return traver(inorder,postorder);
    }
};

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值