重建二叉树
Posted baishouzu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重建二叉树相关的知识,希望对你有一定的参考价值。
给两个数组,分别是前序和中序的遍历结果。(数组中没有重复的数字)
首先知道二叉树的便利分别是:
先序遍历:根左右;
中序遍历:左根右;
后续遍历:左右根;
即根在哪一个位置,就是哪一种遍历方式,其中左右的顺序是不变的。
一个经验之谈:涉及到二叉树问题的时候,大部分二叉树问题都可以通过递归方式解决。
题解:构建一个二叉树,第一步需要找到二叉树的根节点;
1)由先序遍历的数组可以知道,preOrder中的第一个数值 X 一定是二叉树的根节点;
2)由中序遍历的结果可以知道,inOrder中,X为根节点,X的左边部分一定是二叉树根节点的左孩子,X的右边部分则是根节点的右孩子;
3)同理,根据先序中的每一个节点作为根节点,在中序中找到该节点的左右孩子。
在代码的实现过程中,为了方便函数的写法和理解,将先序遍历结果数组preOrder设置成为一个全局变量,然后将中序遍历结果inOrder构建成一个哈希表,在哈希表中,以inOrder的数值为key,inOrder的数值下标作为value,如此是为了方便得到中序遍历数组中某个数X为根节点的下标。
完整代码如下:
1 /** 2 * @author: wooch 3 * @create: 2020/02/21 4 */ 5 6 import java.util.HashMap; 7 8 /** 9 * 面试题07. 重建二叉树 10 * 输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。 11 * 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 12 */ 13 public class P07_BuildTree { 14 int preIndex = 0;// preOrder的下标 15 int[] preOrder; 16 int[] inOrder;// 其实这个没有实际作用,只是写上了 17 HashMap<Integer, Integer> map = new HashMap<>();// inOrder的map 18 19 public TreeNode buildTree(int[] preOrder, int[] inOrder) { 20 if (preOrder == null) { 21 return null; 22 } 23 int len = preOrder.length; 24 if (len == 0) { 25 return null; 26 } 27 int i = 0; 28 for (Integer val : inOrder) { 29 map.put(val, i++); 30 } 31 this.preOrder = preOrder; 32 this.inOrder = inOrder; 33 return buildTree(0, len); 34 } 35 36 public TreeNode buildTree(int inStart, int inEnd) { 37 // 该根节点的孩子节点为空 38 if (inStart == inEnd) { 39 return null; 40 } 41 // 构建根节点 42 int rootVal = preOrder[preIndex]; 43 TreeNode root = new TreeNode(rootVal); 44 // 得到根节点在inOrder中的下标 45 int inIndex = map.get(rootVal); 46 // preOrder中下一个数字继续作为根节点 47 preIndex++; 48 // 递归构建二叉树根节点的左右孩子 49 root.left = buildTree(inStart, inIndex); 50 root.right = buildTree(inIndex + 1, inEnd); 51 return root; 52 } 53 }
思考:既然可以通过先中得二叉树,是否还可以根据先后和中后得到二叉树呢?我觉得思路应该差不多!!!
但实际情况则是先后遍历的结果是得不到一棵唯一的二叉树的,中后的话则可以。
因为在中后中,后序遍历可以唯一确定根节点,再通过中序确定左右孩子节点。
但是在先后中,两个都可以确定根节点,但同时造成一个问题,都得不到根节点的左右孩子节点。
因此要通过两种遍历数组得到一颗唯一的二叉树,那么至少要有一个中序遍历的结果,中序遍历最重要的就是可以唯一确定二叉树中每一个节点的左右孩子节点。
以上是关于重建二叉树的主要内容,如果未能解决你的问题,请参考以下文章