Day 4:重建二叉树

Posted 一计之长妙算天下

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day 4:重建二叉树相关的知识,希望对你有一定的参考价值。

剑指Offer_编程题——重建二叉树

题目描述:

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

具体要求:

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++32M,其他语言64M

具体思路:

思路1:
背景知识介绍:
  首先我们应该了解的是:
  前序遍历的顺序是:根——左结点——右结点
  中序遍历的顺序是:左结点——根——右结点
  因此,对于前序遍历序列,其实就是“根”的遍历,1是第一个遍历到的根,2是第二个会遍历的根,4 是第三个……
  而对于中序遍历序列,对于根节点1来说,它的左边全是左子树[4,7,2],右边全部为它的右子树[5,3,8,6],而在左子树中,如何判断谁是根节点呢,看前序遍历中的下一个结点“2”,因为对于1来说,它的左子树的根节点,肯定是前序遍历中1 的下一个结点。因此,对于以结点2为根节点的子树,左边的[4,7]为它的左子树,而右边没有子树……以此类推出整个树的结构。
代码实现思路:
1、用两个下标在中序遍历序列中控制遍历的数组范围(每一次遍历某一颗子树),比如下标x=0,下标y=3,则只遍历根节点为1的左子树
2、在前序遍历中,用一个pre_index来控制根节点的遍历位置,每遍历过一个子树根节点,pre_index+1.
具体我们用java来实现该思路,通过前序和中序遍历重建二叉树。

public class Solution { private int [] pre; private int pre_index = 0; public TreeNode LeftNodeAndRightNode(int x,int y,int shuzu[]){ int index = Find (pre[this.pre_index++],x, y,shuzu); TreeNode temp = new TreeNode(shuzu[index]); if (index != x){ temp.left = LeftNodeAndRightNode(x, index-1, shuzu); } if(index != y){ temp.right = LeftNodeAndRightNode(index+1, y, shuzu); } return temp; } public int Find(int target,int x,int y,int shuzu[]){ int i; for (i = x; i<= y;i++){ if(shuzu[i]==target){ break; } } return i; } public TreeNode reConstructBinaryTree(int []pre,int [] in){ TreeNode tn = new TreeNode(pre[0]); this.pre = pre; int in_len = in.length; int rootNode_index = Find(pre[pre_index++],0,in_len,in); if(rootNode_index !=0){ tn.left = LeftNodeAndRightNode(0,rootNode_index-1, in); } if(rootNode_index != in_len -1){ tn.right = LeftNodeAndRightNode(rootNode_index+1,in_len-1,in); } return tn; }}

如果你是需要通过牛客网编程测试,以上代码即可通过,因为在那款编译器定义了树的结构。但是如果你要在本地编译器IDEA或者eclipse,就需要定义树的结构,否则编译显示错误。
树的定义用java实现如下:

public class TreeNode{ int val; TreeNode left; TreeNode right; TreeNode(int x){ val = x; }}

其效果如图所示:

思路2:
  本题主要采用递归的思想。首先介绍一下根据前序遍历和中序遍历来构建二叉树的思想:前序遍历的第一个则是二叉树的根,找到根在中序遍历中的位置,则根将中序遍历分为了两部分,根的左边为二叉树的左子树,根的右边为二叉树的右子树,对应的左右子树在可前序遍历中是连续存在的,根据该思路可以继续分别寻找左子树和右子树的根节点,递归进行。首先判断二叉树是否为空,进行长度的判断即可。还要注意将根定义成节点的形式。在进行本函数的递归调用时,需要在本函数名前加上self.。
具体用python实现如下:

class Solution: # 返回构造的TreeNode根节点 def reConstructBinaryTree(self, pre, tin): # write code here if len(pre) == 0: return None root_data = TreeNode(pre[0]) i = tin.index(pre[0]) root_data.left = self.reConstructBinaryTree(pre[1:1+i],tin[:i]) root_data.right = self.reConstructBinaryTree(pre[1+i:],tin[i+1:])        return root_data

以下是用python实现二叉树定义

class TreeNode: def __init__(self, x): self.val = x self.left = None    self.right = None

其效果如图所示:

总结

  本道题主要考察树的相关知识,包括树的中序遍历和先序遍历,这里主要考察的是根据给出的先序遍历和中序遍历,可以确定一颗二叉树,并且也考察了递归的思维。在做题之前,我们应该先看看树的相关基本知识,包括树的建立、树的存储、树的三种遍历,尤其是二叉树在日常生活中应用最广,需要我们重点掌握。从这道题让我体会到,日常的基础很重要,我们刷题是为了巩固我们的基础知识,尤其是《数据结构》相关的,因此,我们在做题之前,应该先掌握《数据结构》基础知识,这样刷题的效果是最好的,真正的做到学以致用。继续加油,争取早日找到工作,Good Luck!!!

以上是关于Day 4:重建二叉树的主要内容,如果未能解决你的问题,请参考以下文章

前端每日一题:Day5-重建二叉树

4.重建二叉树

重建二叉树

[编程题]重建二叉树

重建二叉树

剑指Offer -- 重建二叉树(详细思路)