重建二叉树(C++)

重建二叉树

描述

  给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。

  例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示。

效果图

提示:

  1. vin.length == pre.length
  2. pre 和 vin 均无重复元素
  3. vin出现的元素均出现在 pre里
  4. 只需要返回根结点,系统会自动输出整颗树做答案对比

数据范围:

效果图

要求:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)

示例1

输入:
[1,2,4,7,3,5,6,8],[4,7,2,1,5,3,8,6]
返回值:
{1,2,3,4,#,5,6,#,7,#,#,8}
说明:
返回根节点,系统会输出整颗二叉树对比结果,重建结果如题面图示  

示例2

输入:
[1],[1]
返回值:
{1}

示例3

输入:
[1,2,3,4,5,6,7],[3,2,4,1,6,5,7]
返回值:
{1,2,5,3,4,6,7}

解题思想

根据遍历序列确定二叉树

  若二叉树各节点的值均不相同,任意一颗二叉树结点的先序序列、中序序列和后序序列都是唯一的。反过来,若已知二叉树遍历的任意两种序列,能否确定这颗二叉树呢?这样确定的二叉树是否是唯一的呢?

  由二叉树的先序序列和中序序列,或由其后序序列和中序序列均能唯一地确定一棵二叉树。

  根据定义,二叉树的先序遍历是先访问根节点,其次再按先序遍历方式遍历根结点的左子树,最后按先序遍历方式遍历根结点的右子树。这就是说,在先序遍历中,第一个结点一定是二叉树的根结点。另一方面,中序遍历是先遍历左子树,然后访问根结点,最后再遍历右子树。这样,根结点在中序序列中必然将中序序列分割成两个子序列,前一个子序列是根结点的左子树的中序序列,而后一个子序列是根结点的右子树的中序序列。根据这两个子序列,在先序序列中找到对应的左子序列和右子序列。在先序序列中,左子序列的第一个结点是左子树的根结点,右子序列的第一个结点是右子树的根结点。这样,就确定了二叉树的三个结点。同时,左子树和右子树的根结点又可以分别把左子序列和右子序列划分成两个子序列,如此递归下去,当取尽先序序列中的结点时,便可以得到一颗二叉树。

  同理,由二叉树的后序序列和中序序列也可唯一地确定一棵二叉树。因为,依据后序遍历和中序遍历的定义,后序序列的最后一个结点,就如同先序序列的第一个结点一样,可将中序序列分成两个子序列,分别为这个结点左子树的中序序列和右子树的中序序列,,再拿出后序序列的倒数第二个结点,并继续分割中序序列,如此递归下去,当倒着取尽后序序列中的结点时,便可以得到一颗二叉树。

源代码

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
  public:
    TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin) {
        if (pre.size() == 0)return nullptr;
        TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode*));
        vector<int> leftPre, leftVin, rightPre, rightVin;
        node->val = pre[0];
        int left = 0;
        bool flag = false;
        for (int i = 0; i < vin.size(); i++) {
            if (pre[0] == vin[i]) {
                left = i;
                break;
            }
        }

        for (int i = 0; i < left; i++) {
            leftPre.push_back(pre[i + 1]);
            leftVin.push_back(vin[i]);
        }

        for (int i = left + 1; i < pre.size(); i++) {
            rightPre.push_back(pre[i]);
            rightVin.push_back(vin[i]);
        }

        node->left = reConstructBinaryTree(leftPre, leftVin);
        node->right = reConstructBinaryTree(rightPre, rightVin);
        return node;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ufgnix0802

总结不易,谢谢大家的支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值