牛客网剑指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行的代码,其定义的四个变量,所代表的含义,为何要这四个变量,以及如何能够递归的定义他们。

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

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

posted @ 2020-04-04 13:01  少年π  阅读(186)  评论(0编辑  收藏  举报