题目
给定两个整数数组 preorder
和 inorder
,其中 preorder
是二叉树的先序遍历, inorder
是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例 1:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]
示例 2:
输入: preorder = [-1], inorder = [-1]
输出: [-1]
提示:
1 <= preorder.length <= 3000
inorder.length == preorder.length
-3000 <= preorder[i], inorder[i] <= 3000
preorder
和inorder
均 无重复 元素inorder
均出现在preorder
preorder
保证 为二叉树的前序遍历序列inorder
保证 为二叉树的中序遍历序列
前置知识:
preorder
:前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点--->根的左子树--->根的右子树。
inorder:
中序遍历(Inorder Traversal)——根的左子树--->根节点--->根的右子树
前序遍历所得的第一个节点就是根节点,所以可以用来确定的是root根节点在中序遍历的位置,
再根据中序遍历,root根节点的左边是这棵二叉树的左树,root根节点的右边是这课二叉树的右树来构建这课二叉树
以示例1为例谈谈对题目的理解
示例1输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
preorder = [ 3, 9, 20, 15, 7 ] 3就为这棵二叉树的root根节点
inorder = [ 9, 3, 15, 20, 7 ] 9为root的左树,并且只有一个节点,所以9为root的左节点
15,20,7这三个节点为root的右树,再根据中序遍历根的左子树--->根节点--->根的右子树可得
root的右节点为20这个节点,20节点的左节点为15这个节点,右节点为7这个节点
画图演示上述文字说明
解题思路:
根据题目所给的前序遍历的节点顺序在中序遍历中进行递归来构建二叉树
1.根据前序遍历找到中序遍历根节点iRoot的位置,创建根节点,再确定iBegin,iEnd的位置,i++;
2.对iBegin和iEnd的位置进行判断,当iBegin>iEnd时,返回null,递归开始回退;
2.在中序遍历当中,根据iRoot ,iBegin,iEnd的位置,并进行左树和右树的构建;
对上述三步进行递归,递归完了之后,二叉树构建完成,返回根节点root
注:对前序遍历所得节点的利用才是本题代码的灵魂所在
图示:
解题代码
class Solution {
public int i = 0;
public TreeNode buildTree(int[] preorder, int[] inorder) {
return create_a_binary_tree(preorder, inorder, 0, inorder.length - 1);
}
public TreeNode create_a_binary_tree(int[] preorder, int[] inorder, int inBegin, int inEnd) {
if (inBegin > inEnd) {
return null;
//给定的数组int[] preorder, int[] inorder,遍历完了,没有子树了,该节点为空节点,返回null,递归开始回退
}
//先根据先序遍历创建根节点
TreeNode root = new TreeNode(preorder[i]);
//找到当前根节点,在中序遍历的位置
int rootIndex = findIndex(inorder, inBegin, inEnd, preorder[i]);
i++;
//递归构建左树
root.left = create_a_binary_tree(preorder, inorder, inBegin, rootIndex - 1);
//递归构建右树
root.right = create_a_binary_tree(preorder, inorder, rootIndex + 1, inEnd);
//前序遍历完成,返回根节点
return root;
}
private int findIndex(int[] inorder, int inBegin, int inEnd, int key) {
for (int j = inBegin; j <= inEnd; j++) {
if (inorder[j] == key) {
return j;
}
}
return -1;
}
}
运行结果
题目链接
https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/submissions/
举一翻三,再来一道
根据一棵树的中序遍历与后序遍历构造二叉树
给定两个整数数组
inorder
和postorder
,其中inorder
是二叉树的中序历,postorder
是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
示例 1:
输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]
示例 2:
输入:inorder = [-1], postorder = [-1]
输出:[-1]
后序遍历(Postorder Traversal)——根的左子树--->根的右子树--->根节点。
创建根节点后,先创建右数,再创建左树
根据示例1进行讲解,下图是代码递归过程
随着代码的递归,二叉树随之构建的过程
解题代码
public class Solution {
public int i = 0;
public TreeNode buildTree(int[] inorder, int[] postorder) {
i = postorder.length - 1;
return create_a_binary_tree(postorder, inorder, 0, inorder.length - 1);
}
public TreeNode create_a_binary_tree(int[] postorder, int[] inorder, int inBegin, int inEnd) {
if (inBegin > inEnd) {
return null;
//给定的数组int[] postorder, int[] inorder,遍历完了,没有子树了,该节点为空节点,返回null,递归开始回退
}
//先根据先序遍历创建根节点
TreeNode root = new TreeNode(postorder[i]);
//找到当前根节点,在中序遍历的位置
int rootIndex = findIndex(inorder, inBegin, inEnd, postorder[i]);
i--;
//递归先构建右树
root.right = create_a_binary_tree(postorder, inorder, rootIndex + 1, inEnd);
//递归后构建左树
root.left = create_a_binary_tree(postorder, inorder, inBegin, rootIndex - 1);
//前序遍历完成,返回根节点
return root;
}
private int findIndex(int[] inorder, int inBegin, int inEnd, int key) {
for (int j = inBegin; j <= inEnd; j++) {
if (inorder[j] == key) {
return j;
}
}
return -1;
}
}
运行结果
题目链接:
https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/submissions/
完结撒花✿✿ヽ(°▽°)ノ✿✿