问题 已知一棵二叉树的先序遍历以及中序遍历,重建二叉树。二叉树的每一个节点有三个属性,左子节点,右子节点,以及节点值。
思路 先序遍历服从规则“根左右” ,所以由此可知,对于一个先序遍历得到的数组,第一个元素一定是根节点 ;
中序遍历服从规则”左根右“ ,所以由此可知,对于一个中序遍历得到的数组,根节点左边的元素都属于根节点的左子树 ,而根节点右边的元素都属于根节点的右子树 ;
所以,我们可以先通过先序遍历的第一个元素确定根节点,然后通过中序遍历结合根节点,获得当前根节点的左右子树,再将子树看成一棵独立的树,继续使用先序遍历判断根节点,中序遍历判断子树的方式,最终建立起整棵树;
例子 假设有一棵二叉树,先序遍历为{1,2,4,7,3,5,6,8} ,中序遍历为{4,7,2,1,5,3,8,6} ,则建树过程如下:
首先,通过先序遍历可知树的根节点为1 ,则在中序遍历中,1左边的元素4,7,2 即为根的左子树的元素,而1 右边的元素5,3,8,6 即为根节点的右子树;
对于左子树4,7,2 来说,在先序遍历中,这三个点的顺序为2,4,7 ,则2 为根节点,而在中序遍历中,4,7 均在2 的左边,则4,7 均为以2 为根树的左子树,且没有右子树;
对于4,7 这两个节点来说,先序遍历中,4 节点在7节点之前,所以4 为根节点,而7 作为子树,在中序遍历中,7 在4 之后,所以7 为右子树;
对于根节点1 的右子树5,3,8,6 来说,在先序遍历中,3 在最前面,所以3 为这棵子树的根节点,而在中序遍历中,5 在3 的左边,所以属于左子树,而8,6 在3 的右边,属于右子树;
对于根节点3 的右子树8,6 ,在先序遍历中,6 在8 之前,所以,6 又为根节点,而在中序遍历中,8 在6 的左边,所以8 是6 的左子节点;
至此,二叉树便重建完成;
代码 树的节点 1 2 3 4 5 6 7 8 9 public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } }
建树方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public TreeNode reConstructBinaryTree (int [] pre, int [] in) { if (pre.length == 0 ) { return null ; } int root = pre[0 ]; TreeNode node = new TreeNode(root); int i = 0 ; for ( ; i<in.length; ++i) { if (in[i] == root) { break ; } } int [] leftIn = Arrays.copyOfRange(in, 0 , i); int [] leftPre = Arrays.copyOfRange(pre, 1 , i+1 ); node.left = reConstructBinaryTree(leftPre, leftIn); int [] rightIn = Arrays.copyOfRange(in, i+1 , in.length); int [] rightPre = Arrays.copyOfRange(pre, i+1 , pre.length); node.right = reConstructBinaryTree(rightPre, rightIn); return node; }
建树代码(优化) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public TreeNode reConstructBinaryTree (int [] pre, int [] in) { return getRootTreeNode(pre, 0 , pre.length-1 , in, 0 , in.length-1 ); } public TreeNode getRootTreeNode (int [] pre, int preL, int preR, int [] in, int inL, int inR) { if (preL > preR) { return null ; } TreeNode node = new TreeNode(pre[preL]); for (int i=inL; i<=inR; ++i) { if (in[i] == pre[preL]) { node.left = getRootTreeNode(pre, preL+1 , preL+i-inL, in, inL, i-1 ); node.right = getRootTreeNode(pre, preL+i-inL+1 , preR, in, i+1 , inR); break ; } } return node; }
最后更新时间:2019-10-10 13:23:50
世界是个球,前方总有路!