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:重建二叉树的主要内容,如果未能解决你的问题,请参考以下文章