要求:
根据一棵树的前序遍历与中序遍历构造二叉树
示例:
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回:
3
/ \
9 20
/ \
15 7
思路:
就拿示例数组来说,前序遍历数组构成为:[根,左子树,右根,右子树],中序遍历的数组为:[左子树,根,右子树]。所以步骤为:
- 先得到前序遍历数组的第一个元素,这个元素就是根节点,再去中序遍历的数组中找根节点这个元素,得到其在数组中的索引,以此为分界点,前面是左子树,右边是右子树。自然也能得到左右子树元素的个数。
- 根据得到的左右子树的元素个数,再去前序数组里面划定范围,左右子树的范围,由此展开递归。
- 左子树的第一个元素也必为左子树的根节点
- 右子树的第一个元素也必为右子树的根节点
- 得到根节点后再去中序数组里面找根节点的索引,再去划分范围,再这样去递归
- 递归终止条件:左边界索引大于右边界索引
- 注意:可以先对中序遍历进行Map存储,这样查找元素及索引的时候会很快
代码:
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
class Solution {
private Map<Integer, Integer> indexMap;
public TreeNode buildTree(int[] preorder, int[] inorder) {
int len = preorder.length;
indexMap = new HashMap<Integer, Integer>();
for (int i = 0; i < len; i++) {
indexMap.put(inorder[i], i);
}
return mybuilderTree(preorder, 0, len-1, inorder, 0, len-1);//前序数组中,数组左边界,数组右边界,中序数组中,数组左边界,数组右边界
}
public TreeNode mybuildTree(int[] preorder, int left1, int right1, int[] inorder, int left2, int right2) {
if (left1 > right1) return null;
if (left2 > right2) return null;
int root1 = left1;
int root2 = indexMap.get(preorder[root1]);
int size = root2 - left2;
TreeNode root = new TreeNode(preorder[root1]);//先建立根节点
root.left = mybuildTree(preorder, left1+1, left1+size, inorder, left2, root2-1);
root.right = mybuildTree(preorder, left1+size+1, right1, inorder, root2+1, right2);
return root;
}
}