Day 4:重建二叉树

时间:2022-07-24
本文章向大家介绍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!!!