⭐️前言⭐️
本篇文章主要总结通过前序遍历、中序遍历、后序遍历中的两个遍历结果,来构造二叉树的过程,通过本篇文章的总结,可以解决一下问题。
LeetCode | 难度 |
---|---|
654. 最大二叉树 | 🟠 |
105. 从前序与中序遍历序列构造二叉树 | 🟠 |
106. 从中序与后序遍历序列构造二叉树 | 🟠 |
889. 根据前序和后序遍历构造二叉树 | 🟠 |
剑指 Offer 07. 重建二叉树 | 🟠 |
🍉欢迎点赞 👍 收藏 ⭐留言评论 📝私信必回哟😁
🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言
🍉博客中涉及源码及博主日常练习代码均已上传GitHub
📍内容导读📍
- 🍅构建最大二叉树
- 🍅前序中序构建
- 🍅中序后序构建
- 🍅前序后序构建
🍅构建最大二叉树
654. 最大二叉树
题解思路:
首先遍历数组找到最大值maxValue
,从而把根节点root
构造出来,然后对maxValue
左边的数组和右边的数组进行递归构建,作为root
的左右子树。
按照题目给出的例子,输入的数组为[3,2,1,6,0,5]
,对于整棵树的根节点来说,其实是在做这件事。
TreeNode constructMaximumBinaryTree([3,2,1,6,0,5]) {
// 找到数组中的最大值
TreeNode root = new TreeNode(6);
// 递归调用构造左右子树
root.left = constructMaximumBinaryTree([3,2,1]);
root.right = constructMaximumBinaryTree([0,5]);
return root;
}
代码实现:
/* 主函数 */
TreeNode constructMaximumBinaryTree(int[] nums) {
return build(nums, 0, nums.length - 1);
}
// 定义:将 nums[lo..hi] 构造成符合条件的树,返回根节点
TreeNode build(int[] nums, int lo, int hi) {
// base case
if (lo > hi) {
return null;
}
// 找到数组中的最大值和对应的索引
int index = -1, maxVal = Integer.MIN_VALUE;
for (int i = lo; i <= hi; i++) {
if (maxVal < nums[i]) {
index = i;
maxVal = nums[i];
}
}
// 先构造出根节点
TreeNode root = new TreeNode(maxVal);
// 递归调用构造左右子树
root.left = build(nums, lo, index - 1);
root.right = build(nums, index + 1, hi);
return root;
}
🍅前序中序构建
105. 从前序与中序遍历序列构造二叉树
剑指 Offer 07. 重建二叉树
题解思路:
前序遍历的第一个值preorder[0]
就是根节点的值,通过在中序遍历中找到该值,就确定了左右子树值的范围。将划分开的区域递归下去进行构建,就完成了二叉树的构建。
leftSize:左子树节点的个数=index-inStart
代码实现:
class Solution {
HashMap<Integer,Integer> valToIndex=new HashMap<>();
// 通过哈希表存储中序遍历数据对应的索引
public TreeNode buildTree(int[] preorder, int[] inorder) {
for(int i=0;i<inorder.length;i++) {
valToIndex.put(inorder[i],i);
}
return build(preorder,0,preorder.length-1,
inorder,0,inorder.length-1);
}
TreeNode build(int[] preorder,int preStart,int preEnd,
int[] inorder,int inStart,int inEnd) {
if(preStart>preEnd) {
return null;
}
int rootVal=preorder[preStart];
int index=valToIndex.get(rootVal);
int leftSize=index-inStart;
// 先构造出当前根节点
TreeNode root=new TreeNode(rootVal);
// 递归构造左右子树
root.left=build(preorder,preStart+1,preStart+leftSize,
inorder,inStart,index-1);
root.right=build(preorder,preStart+leftSize+1,preEnd,
inorder,index+1,inEnd);
return root;
}
}
🍅中序后序构建
106. 从中序与后序遍历序列构造二叉树
题解思路:
与上题前序、中序遍历结果构建相似,只是二叉树的根节点是后序遍历的最后一个节点,确定根节点后再去中序遍历中找到位置,划分左右子树,后续操作与上题相似。
代码实现:
class Solution {
HashMap<Integer,Integer> map=new HashMap<>();
public TreeNode buildTree(int[] inorder, int[] postorder) {
for(int i=0;i<inorder.length;i++) {
map.put(inorder[i],i);
}
return buildTree(inorder,0,inorder.length-1,
postorder,0,postorder.length-1);
}
TreeNode buildTree(int[] inorder,int inStart,int inEnd,
int[] postorder,int postStart,int postEnd) {
if(inStart>inEnd) {
return null;
}
int rootValue=postorder[postEnd];
int index=map.get(rootValue);
int leftSize=index-inStart;
TreeNode root=new TreeNode(rootValue);
root.left=buildTree(inorder,inStart,index-1,
postorder,postStart,postStart+leftSize-1);
root.right=buildTree(inorder,index+1,inEnd,
postorder,postStart+leftSize,postEnd-1);
return root;
}
}
🍅前序后序构建
889. 根据前序和后序遍历构造二叉树
题解思路:
通过前序中序,或者后序中序遍历结果可以确定唯一一棵二叉树,但是通过前序后序遍历结果无法确定唯一的一棵二叉树,所以该题返回一种可能即可。
构造思路与上边的题目类似。
1.首先把前序遍历结果的第一个元素或者后序遍历的最后一个元素确定为根节点的值。
2.然后把前序遍历结果的第二个元素作为左子树的根节点的值。(其实左子树有可能为空指针,所以答案不唯一)
3.在后序遍历结果中寻找左子树根节点的值,从而确定了左子树的索引边界,进而确定右子树的索引边界,递归构造左右子树即可。
代码实现:
class Solution {
HashMap<Integer, Integer> valToIndex = new HashMap<>();
public TreeNode constructFromPrePost(int[] preorder, int[] postorder) {
for (int i = 0; i < postorder.length; i++) {
valToIndex.put(postorder[i], i);
}
return build(preorder, 0, preorder.length - 1,
postorder, 0, postorder.length - 1);
}
TreeNode build(int[] preorder,int preStart,int preEnd,
int[] postorder,int postStart,int postEnd) {
if (preStart > preEnd) {
return null;
}
if (preStart == preEnd) {
return new TreeNode(preorder[preStart]);
}
// root 节点对应的值就是前序遍历数组的第一个元素
int rootVal = preorder[preStart];
// root.left 的值是前序遍历第二个元素
// 通过前序和后序遍历构造二叉树的关键在于通过左子树的根节点
// 确定 preorder 和 postorder 中左右子树的元素区间
int leftRootVal = preorder[preStart + 1];
// leftRootVal 在后序遍历数组中的索引
int index = valToIndex.get(leftRootVal);
// 左子树的元素个数
int leftSize = index - postStart + 1;
// 先构造出当前根节点
TreeNode root = new TreeNode(rootVal);
root.left=build(preorder,preStart+1,preStart+leftSize,
postorder,postStart,index);
root.right=build(preorder,preStart+leftSize+1,preEnd,
postorder,index+1,preEnd-1);
return root;
}
}
⭐️最后的话⭐️
总结不易,希望uu们不要吝啬你们的👍哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正😁