输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
二叉树一般都是递归创建,不然得写多少代码。
本题是由先序和中序重新创建一颗二叉树,首先分析递归的边界。
-
先序序列中的1指定是树的首节点,那么从中序序列中得知1的左边有(4,7,2)右边有(5,3,8,6),即1的左边有3个节点,1的右边有4个节点。如下图
-
同理,先序序列中的2,是1的左边的第一个节点,同时,2的左边有(4,7)右边没有。 即:2的左边有两个节点,右边没有节点。如下图
此时2的右节点为空,怎么判断的呢,因为2在中序序列的右边是1,而1是首节点,所以2的右边是空。 -
我们依次遍历先序序列,并找出先序序列中的元素在中序序列中的位置,进而确定左右节点。
《下面这两条总结的不是很好》 -
递归产生:依次遍历先序序列,找出先序序列中此元素在中序中的下标,利用该下标可以得出有多个个元素在该元素的左边,同时可以得出多少个元素在该元素的右边,并将该元素加入树中。
-
边界定义:在中序序列中定位的下标左右没有能够可用的节点时,就会返回空值。
代码详解
private Map<Integer, Integer> indexForInOrders = new HashMap<>();
public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
for (int i = 0; i < in.length; i++)
indexForInOrders.put(in[i], i);
return reConstructBinaryTree(pre, 0, pre.length - 1, 0);
}
//参数的意思,pre代表的是先序序列,preL代表序列的最左边,而preR代表序列的最右边,intL表示的是:由于先序序列中的元素在中序序列的定位,可以将中序序列分割成两个,inL表示的就是两个序列的最左边的下标。
private TreeNode reConstructBinaryTree(int[] pre, int preL, int preR, int inL) {
if ( preL >preR)//边界条件
return null;
TreeNode root = new TreeNode(pre[preL]);
int inIndex = indexForInOrders.get(root.val);
int leftTreeSize = inIndex - inL;
root.left = reConstructBinaryTree(pre, preL + 1, preL + leftTreeSize, inL);
root.right = reConstructBinaryTree(pre, preL + leftTreeSize + 1, preR, inL + leftTreeSize + 1);
return root;
}
*第一次思考这个题,还是不够清晰