目录
『LeetCode|每日一题』从前序与中序遍历序列构造二叉树
每日一句
人生需要准备的,不是昂贵的茶,而是喝茶的心情
作者简介
🏡个人主页:XiaoChen_Android
📚学习专栏:力扣专栏
🕒发布日期:2022/8/22
『LeetCode|每日一题』从前序与中序遍历序列构造二叉树
1.每日一题
2.解题思路
2.1 思路分析
首先介绍一下二叉树的遍历:
- 前序遍历顺序:根节点--->左子树--->右子树
- 中序遍历顺序:左子树--->根节点--->右子树
- 后序遍历顺序:左子树--->右子树--->根节点
此题我们只要了解前序遍历和中序遍历的顺序即可,前序遍历先访问根节点,根节点通过中序遍历可以区分左子树和右子树,然后再在每个左子树右子树中递归寻找其中的根节点,一层一层往下找,就可以构造出这个二叉树;
S1:首先要定义好这个递归函数所需要的参数,前序遍历和中序遍历的数组必不可少,由于根节点至关重要,所以我们可以把根节点及其下标放到一个HashMap中方便寻找;
S2:我们还需要区分左子树和右子树,所以需要左子树的区间和右子树的区间,前序遍历和中序遍历都需要知到左右子树的区间;
S3:递归函数退出的条件,可以利用定义的区间来判断,当pLeft > pRight或者iLeft > iRight时,不满足区间要求,返回空;
S4:递归之前需要先找到根节点,假设为root,它的值为rootval,那么它的下标就可以用map通过rootval为索引找到下标;
S5:最重要的一步就是通过根节点的下标来找到左子树的区间和右子树的区间:(如图所示)读者可以自己举例来找出这个左右子树区间下标的计算方法
- 首先看左子树:设根节点的下标为index,在中序遍历中,左子树的区间很容易得出,即(iLeft , index - 1);在前序遍历中,左子树的区间稍微麻烦一点,即(pLeft , index - iLeft + pLeft),就是从根节点的下一个元素开始,结束的位置其实就是左子树的长度加上左子树的起始下标:index - 1 - iLeft(长度)+ pLeft + 1(起始坐标);
- 接着找右子树:在中序遍历中,右子树的起始下标为根节点的下一位,结束坐标就是中序遍历的最右端,即(index + 1 , iRight);在前序遍历中,起始坐标就是左子树的末尾坐标加一,结束坐标就是前序遍历的最右端,即(index - iLeft + pLeft + 1 , pRight);
S6:最后返回定义出来的这个root即可;
2.2 核心代码(递归)
public TreeNode buildTreeNode(int[] preorder , int pLeft , int pRight , int[] inorder ,
int iLeft , int iRight , Map<Integer , Integer> map){
//退出递归条件
if(pLeft > pRight || iLeft > iRight){
return null;
}
//根节点
int rootval = preorder[pLeft];
TreeNode root = new TreeNode(rootval);
int index = map.get(rootval);
//左节点
root.left = buildTreeNode(preorder , pLeft + 1 , index - iLeft + pLeft , inorder ,
iLeft , index - 1 , map);
//右节点
root.right = buildTreeNode(preorder , index - iLeft + pLeft + 1 , pRight , inorder ,
index + 1 , iRight);
return root;
}
2.3 完整代码
/**
* 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) {
int preLen = preorder.length;
int inoLen = inorder.length;
//把中序遍历的值和对应下表存到hash表中
Map<Integer , Integer> map = new HashMap<>(preLen);
for(int i = 0; i < inoLen ; i++){
map.put(inorder[i] , i);
}
return buildTreeNode(preorder , 0 , preLen - 1 , inorder , 0 , iRight - 1 , map);
}
public TreeNode buildTreeNode(int[] preorder , int pLeft , int pRight , int[] inorder ,
int iLeft , int iRight , Map<Integer , Integer> map){
//退出递归条件
if(pLeft > pRight || iLeft > iRight){
return null;
}
//根节点
int rootval = preorder[pLeft];
TreeNode root = new TreeNode(rootval);
int index = map.get(rootval);
//左节点
root.left = buildTreeNode(preorder , pLeft + 1 , index - iLeft + pLeft , inorder ,
iLeft , index - 1 , map);
//右节点
root.right = buildTreeNode(preorder , index - iLeft + pLeft + 1 , pRight , inorder ,
index + 1 , iRight);
return root;
}
}
2.4 运行结果
🍁 类似题目推荐:
如果文章对各位大佬有帮助就支持一下噢,新手尝试,不好的地方请各位大佬多多指教!