给定一棵树的前序遍历 preorder 与中序遍历 inorder。请构造二叉树并返回其根节点。
示例 1:
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]
示例 2:
Input: preorder = [-1], inorder = [-1]
Output: [-1]
1.前序遍历的第一个节点一定是根节点,根据这个根节点在中序遍历中的位置,就可以分为左、右子树两个部分,再利用递归实现即可。
/**
* 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) {
if(preorder.length == 0 || inorder.length == 0){
return null;
}
TreeNode root = new TreeNode(preorder[0]);//前序遍历的第一个节点一定是整棵树的子节点
//在中序遍历中找到根节点的位置
for(int i = 0;i < preorder.length;i++){
if(preorder[0] == inorder[i]){
//左右子树的构造就是对两个数组对应的子树组进行树的构造。递归实现
root.left = buildTree(Arrays.copyOfRange(preorder,1,1 + i),Arrays.copyOfRange(inorder,0,i));
root.right = buildTree(Arrays.copyOfRange(preorder,1+i,preorder.length),Arrays.copyOfRange(inorder,i + 1,inorder.length));
break;
}
}
return root;
}
}
2.虽然上面的递归简洁,但是赋值数组效率低,可以优化。
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
return myBuildTree(preorder,inorder,0,preorder.length-1,0,inorder.length-1);
}
public TreeNode myBuildTree(int[] preorder, int[] inorder, int preLeft, int preRight, int inLeft, int inRight) {
if (preLeft > preRight) {
return null;
}
// 前序遍历中的第一个节点就是根节点
int preRoot = preLeft;
// 在中序遍历中定位根节点
int inRoot = 0;
for(int i = 0;i < inorder.length;i++){
if(preorder[preRoot] == inorder[i]){
inRoot = i;
break;
}
}
// 先把根节点建立出来
TreeNode root = new TreeNode(preorder[preRoot]);
// 得到左子树中的节点数目
int sizeLeftSubtree = inRoot - inLeft;
// 递归地构造左子树,并连接到根节点
// 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
root.left = myBuildTree(preorder, inorder, preLeft + 1, preLeft + sizeLeftSubtree, inLeft, inRoot - 1);
// 递归地构造右子树,并连接到根节点
// 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
root.right = myBuildTree(preorder, inorder, preLeft + sizeLeftSubtree + 1, preRight, inRoot + 1, inRight);
return root;
}
}
3.迭代法。官方题解提供的一种解题思路
题解:力扣
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder == null || preorder.length == 0){
return null;
}
Deque<TreeNode> stack = new LinkedList<>();
TreeNode root = new TreeNode(preorder[0]);
stack.push(root);
int indexInorder = 0;
for(int i = 1;i < preorder.length;i++){
TreeNode pNode = stack.peek();
if(pNode.val != inorder[indexInorder]){
pNode.left = new TreeNode(preorder[i]);
stack.push(pNode.left);
}else{
while(!stack.isEmpty() && stack.peek().val == inorder[indexInorder]){
pNode = stack.pop();
indexInorder++;
}
pNode.right = new TreeNode(preorder[i]);
stack.push(pNode.right);
}
}
return root;
}
}
题源:力扣