- 题目描述
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:你可以假设树中没有重复的元素。
来源:LeetCode
- 示例
给出:
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
- 思路分析
- 前序:中 --> 左 --> 右
中序:左 --> 中 --> 右 - 因此从前序确定子树的根节点,然后在中序中找到该节点,中序中在该节点左边的点就在该节点的左子树上,右边的点就在该节点的右子树上。
- 用递归。我这里的递归写得比较麻烦,讨论区里面有很简洁的。
- JAVA实现
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
TreeNode root = new TreeNode();
if(preorder.length == 0) return null;
HashMap<Integer, Integer> hash = new HashMap(); //hash表用来保存某个节点是否被用过
for(int i :preorder) hash.put(i,1);
return build(preorder, inorder, 0, inorder.length-1, hash);
}
public TreeNode build(int[] preorder, int[] inorder, int left, int right, HashMap hash) {
TreeNode root;
if(left == right) {
root = new TreeNode(inorder[left]);
hash.put(inorder[left], 0);
return root;
}
else if(left > right) {
return null;
}
else {
int i, j;
//找到root,是preorder中第一个还未被使用过的数
for(i=0; i<preorder.length; i++) {
if((int)hash.get(preorder[i]) == 1) {
break;
}
}
hash.put(preorder[i], 0);
root = new TreeNode(preorder[i]);
//找到左子树和右子树的范围
for(j=left; j<=right; j++) {
if(inorder[j] == preorder[i]) break;
}
root.left = build(preorder, inorder, left, j-1, hash);
root.right = build(preorder, inorder, j+1, right, hash);
return root;
}
}
}