力扣 105. 从前序与中序遍历序列构造二叉树 题解
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
二叉树结构
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) {
return bulid(preorder, 0, preorder.length - 1, inorder, 0, inorder.length-1);
}
/**
*preorder为前序遍历数组
*preStart为前序遍历的起始指针
*preEnd为前序遍历的结尾指针
*inorder为中序遍历数组
*inStart为中序遍历的起始指针
*inEnd为中序遍历的结尾指针
**/
public TreeNode bulid(int[] preorder, int preStart, int preEnd, int[] inorder, int inStart, int inEnd){
//终止条件
if(preStart > preEnd || inStart > inEnd) return null;
//前序遍历的preStart为树的根
TreeNode root = new TreeNode(preorder[preStart]);
//找到中序遍历中对应值为preorder[preStart]的下标
for(int i=inStart; i<=inEnd; i++){
if(preorder[preStart] == inorder[i]){
/**左子树**/
//前序遍历指针+1,结尾为中序遍历i的位置,减去起始的中序遍历位置再加上preStart
//中序遍历以i为分界点,左右分开
root.left = bulid(preorder, preStart+1, i-inStart+preStart, inorder, inStart, i-1);
/**右子树**/
root.right = bulid(preorder, i-inStart+preStart+1, preEnd, inorder, i+1, inEnd);
}
}
return root;
}
}
优化
因为每一次都需要在中序遍历inorder里面找下标,所以用HashMap存值和下标,方便寻找
class Solution {
HashMap<Integer,Integer> map = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
for(int i=0; i<inorder.length; i++){
map.put(inorder[i], i);
}
return bulid(preorder, 0, preorder.length - 1, inorder, 0, inorder.length-1);
}
/**
*preorder为前序遍历数组
*preStart为前序遍历的起始指针
*preEnd为前序遍历的结尾指针
*inorder为中序遍历数组
*inStart为中序遍历的起始指针
*inEnd为中序遍历的结尾指针
**/
public TreeNode bulid(int[] preorder, int preStart, int preEnd, int[] inorder, int inStart, int inEnd){
//终止条件
if(preStart > preEnd || inStart > inEnd) return null;
//前序遍历的preStart为树的根
TreeNode root = new TreeNode(preorder[preStart]);
//找到中序遍历中对应值为preorder[preStart]的下标
int i = map.get(preorder[preStart]);
/**左子树**/
//前序遍历指针+1,结尾为中序遍历i的位置,减去起始的中序遍历位置再加上preStart
//中序遍历以i为分界点,左右分开
root.left = bulid(preorder, preStart+1, i-inStart+preStart, inorder, inStart, i-1);
/**右子树**/
root.right = bulid(preorder, i-inStart+preStart+1, preEnd, inorder, i+1, inEnd);
return root;
}
}