剑指Offer——重建二叉树
1、题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
2、代码实现
思路分析:
1 package com.baozi.offer; 2 3 /** 4 * 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。 5 * 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 6 * 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。 7 * 8 * @author BaoZi 9 * @create 2019-07-10-18:36 10 */ 11 public class Offer4 { 12 public static void main(String[] args) { 13 int[] p = new int[]{1, 2, 4, 7, 3, 5, 6, 8}; 14 int[] n = new int[]{4, 7, 2, 1, 5, 3, 8, 6}; 15 Offer4 offer4 = new Offer4(); 16 TreeNode root = offer4.reConstructBinaryTree(p, n); 17 offer4.lastPrint(root); 18 } 19 20 //为了进行验证该方法的正确性,写出一个后序遍历的方法 21 public void lastPrint(TreeNode root) { 22 if (root == null) { 23 return; 24 } 25 lastPrint(root.left); 26 lastPrint(root.right); 27 System.out.println(root.val); 28 } 29 30 //由前序序列和中序序列还原二叉树的方法 31 public TreeNode reConstructBinaryTree(int[] pre, int[] in) { 32 //1、先判断给定的前序序列和中序序列的数组是否为空(进行特殊情况的检测) 33 if (pre == null || in == null) { 34 return null; 35 } 36 //2、定义一个hashMap变量,把中序序列的值和它在数组中的位置进行绑定, 37 // 便于通过前序数组中的值定位该值在中序序列数组中的位置 38 java.util.HashMap<Integer, Integer> map = new java.util.HashMap<Integer, Integer>(); 39 for (int i = 0; i < in.length; i++) { 40 map.put(in[i], i); 41 } 42 //3、通过递归的方法实现重建二叉树 43 return preIn(pre, 0, pre.length - 1, in, 0, in.length - 1, map); 44 } 45 //该方法就是具体实现重建二叉树的 46 47 /** 48 * @param p 前序序列的数组 49 * @param pi 前序序列的数组中指向当前待重建子树的左边边界指针 50 * @param pj 前序序列的数组中指向当前待重建子树的右边边界指针 51 * @param n 中序序列的数组 52 * @param ni 中序序列的数组中指向当前待重建子树的左边边界指针 53 * @param nj 中序序列的数组中指向当前待重建子树的左边边界指针 54 * @param map map中存放的是中序序列数组中各个值和它所在位置的对应 55 * @return 56 */ 57 public TreeNode preIn(int[] p, int pi, int pj, int[] n, int ni, int nj, 58 java.util.HashMap<Integer, Integer> map) { 59 //这是结束递归的条件 60 if (pi > pj) { 61 return null; 62 } 63 //递归刚开始的时候前序序列数组中的第一个元素就是该二叉树的根节点 64 TreeNode head = new TreeNode(p[pi]); 65 int index = map.get(p[pi]); 66 //递归的添加该二叉树根节点的左子树和右子树 67 /** 68 * 在重建二叉树的过程中,我们需要判断在当前的根节点下该节点的左子树是那些元素,右子树是那些元素。 69 * 根据前边定义的四个变量,我们不断的划定左子树在前序序列数组中的范围和在中序序列中的范围,每次划定 70 * 范围之后,就能直接找出在该范围内前序序列的pi指针指向的元素就是当前左子树或者右子树的根节点, 71 * 然后的递归的进行不断重复判断,最终就能重建出整个二叉树。 72 */ 73 head.left = preIn(p, pi + 1, pi + index - ni, n, ni, index - 1, map); 74 head.right = preIn(p, pi + index - ni + 1, pj, n, index + 1, nj, map); 75 return head; 76 } 77 } 78 79 //这是题目给定的二叉树中节点的数据结构 80 class TreeNode { 81 int val; 82 TreeNode left; 83 TreeNode right; 84 85 TreeNode(int x) { 86 val = x; 87 } 88 }
后序遍历的运行结果: