zoukankan      html  css  js  c++  java
  • 牛客网剑指offer第4题——重建二叉树

    题目;

    输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

    即根据二叉树的前序遍历结果和中序遍历结果,求解二叉树。

    在这个问题之前,我们先来回顾一些基本概念;

    (1)前序遍历

          a、访问根节点;b、前序遍历左子树(注意这里说的并不是左子节点);c、前序遍历右子树。

    (2)中序遍历

          a、中序遍历左子树;b、访问根节点;c、中序遍历右子树。

    (3)后序遍历

          a、后序遍历左子树;b、后续遍历右子树;c、访问根节点。

    在此,说明一个要点:前、中、后唯一的区别是对根节点的访问次序的差异。我们应该注意是的上面的比如:

     a、访问根节点;b、前序遍历左子树;c、前序遍历右子树。

    这句话表明了,二叉树的遍历,对其子树的遍历,遵循同样的方法。

    思想如下

        a、根据前序遍历结果,第一个元素为二叉树的根结点;

        b、观察中序遍历结果,根结点左侧的为左子树,若左子树根结点前(后)再无任何元素,则左(右)子树的左分支为空;根结点右侧的为右子树,若右子树根结点前(后)再无任何元素,则左(右)子树的左分支为空;

        c、上面的过程是递归的。先找到当前树的根结点,然后划分为左右子树,再进入左子树重复上面的过程,最后进入右子树重复上面的过程,最终还原一棵树。
    代码:

     1 /**
     2  * Definition for binary tree
     3  * struct TreeNode {
     4  *     int val;
     5  *     TreeNode *left;
     6  *     TreeNode *right;
     7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     8  * };
     9  */
    10 class Solution {
    11 public:
    12     TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
    13         if(pre.size() ==0 || vin.size() == 0)
    14             return nullptr;
    15         //难点在于考虑需要定义哪些变量
    16         TreeNode* root  = new TreeNode(pre[0]);//要熟悉new的用法
    17         //找到根节点在中序遍历中的位置,从而将树分为左子树和右子树结构。
    18         int pos;
    19         for( ; pos< vin.size();pos++)
    20             if(vin[pos] == pre[0])
    21                 break;
    22         //重点是传入reConstructBinaryTree的参数是什么?
    23         vector<int> son_vin_left,son_vin_right,son_pre_left,son_pre_right;
    24         //考虑清楚为何要定义这四个变量,意义何在?
    25             for(int i = 0;i <vin.size();i++)
    26             {
    27                 if(i < pos)//重点是对于前序遍历
    28                 {
    29                     son_vin_left.push_back(vin[i]);//考虑会不会越界
    30                     son_pre_left.push_back(pre[i+1]);
    31                 }
    32                 if(i > pos)
    33                 {
    34                     son_vin_right.push_back(vin[i]);//考虑会不会越界
    35                     son_pre_right.push_back(pre[i]);
    36                 }
    37             }
    38             root->left = reConstructBinaryTree(son_pre_left ,son_vin_left);
    39             root->right = reConstructBinaryTree(son_pre_right,son_vin_right);
    40             return root;
    41         
    42     }
    43 };

    对于上述代码的分析如下:

            当左子树结构或者右子树为空,则返回。然后是,找到根节点在中序遍历的位置,于是中序遍历的左侧为左子树,右侧为右子数,对于他们的子树,也是采用同样的方式,因此采用递归的方式处理其左子树和右子树。

    本题的重点是思考第23行的代码,其定义的四个变量,所代表的含义,为何要这四个变量,以及如何能够递归的定义他们。

    前序遍历和后序遍历还原二叉树

    已知前序和中序,后序和中序遍历序列之后,可以唯一确定一棵二叉树。但是,只知道前序和后序遍历序列,是无法知道哪个结点是左子树还算右子树

  • 相关阅读:
    android 手把手教您自定义ViewGroup(一)
    mac下tomcat的安装与配置
    jarsigner签名报错Invalid keystore format
    android上引入七牛 上传图片或者文件 最终整理版本(可用)
    viewpage listview gridview加载本地大图多图OOM处理办法
    android TextView 文字垂直的设置
    javascript技巧之实现add方法无限调用
    jQuery源码分析之ready方法
    jQuery源码分析之Callbacks方法
    jQuery源码分析之extend方法
  • 原文地址:https://www.cnblogs.com/shaonianpi/p/12631377.html
Copyright © 2011-2022 走看看