给定两个整数数组,preorder 和 postorder ,其中 preorder 是一个具有 无重复 值的二叉树的前序遍历,postorder 是同一棵树的后序遍历,重构并返回二叉树。
如果存在多个答案,您可以返回其中 任何 一个。
示例 1:
输入:preorder = [1,2,4,5,3,6,7], postorder = [4,5,2,6,7,3,1]
输出:[1,2,3,4,5,6,7]
示例 2:
输入: preorder = [1], postorder = [1]
输出: [1]
提示:
1 <= preorder.length <= 30
1 <= preorder[i] <= preorder.length
preorder 中所有值都 不同
postorder.length == preorder.length
1 <= postorder[i] <= postorder.length
postorder 中所有值都 不同
保证 preorder 和 postorder 是同一棵二叉树的前序遍历和后序遍历
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-postorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
方法一:递归
思路
前序遍历为:
(根结点) (前序遍历左分支) (前序遍历右分支)
而后序遍历为:
(后序遍历左分支) (后序遍历右分支) (根结点)
例如,如果最终的二叉树可以被序列化的表述为 [1, 2, 3, 4, 5, 6, 7],那么其前序遍历为 [1] + [2, 4, 5] + [3, 6, 7],而后序遍历为 [4, 5, 2] + [6, 7, 3] + [1].
如果我们知道左分支有多少个结点,我们就可以对这些数组进行分组,并用递归生成树的每个分支。
算法
我们令左分支有 LLL 个节点。我们知道左分支的头节点为 pre[1],但它也出现在左分支的后序表示的最后。所以 pre[1] = post[L-1](因为结点的值具有唯一性),因此 L = post.indexOf(pre[1]) + 1。
现在在我们的递归步骤中,左分支由 pre[1 : L+1] 和 post[0 : L] 重新分支,而右分支将由 pre[L+1 : N] 和 post[L : N-1] 重新分支。
作者:LeetCode
链接:https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-postorder-traversal/solution/gen-ju-qian-xu-he-hou-xu-bian-li-gou-zao-er-cha-sh/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
class Solution {
public TreeNode constructFromPrePost(int[] pre, int[] post) {
int N = pre.length;
if (N == 0) return null;
TreeNode root = new TreeNode(pre[0]);
if (N == 1) return root;
int L = 0;
for (int i = 0; i < N; ++i)
if (post[i] == pre[1])
L = i+1;
root.left = constructFromPrePost(Arrays.copyOfRange(pre, 1, L+1),
Arrays.copyOfRange(post, 0, L));
root.right = constructFromPrePost(Arrays.copyOfRange(pre, L+1, N),
Arrays.copyOfRange(post, L, N-1));
return root;
}
}
作者:LeetCode
链接:https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-postorder-traversal/solution/gen-ju-qian-xu-he-hou-xu-bian-li-gou-zao-er-cha-sh/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
解题思路
【生哥刷题】【单片机工程师】
----这里道题目用C语言来做的思路。
树的定义
树是n个结点的有限集。当n=0时,称为空树。
二叉树的定义
二叉树是n个结点的有限集。当n=0时,称为空树,当n不等于0时,根结点包含一个或两个的子树,分别称为左子树个右子树。
二叉树的特点
1.每个结点最多只有两个子树。
2:左子树和右子树是顺序的。
二叉树的抽象表示方法
ADT
{
leftNode; //左子结点
rightNode; //右子结点
data; //数据结点
}
二叉树的遍历方法:
二叉树的遍历是指从根结点出发,按照某种次序依次访问二叉树中的所有结点,使得每个结点都被访问。
关键词:次序 访问
访问:根据具体内容,完成指定的操作
次序:严格按照的顺序完成操作
1:前序遍历->根左右
规则如是二叉树为空,则返回空操作,否则先访问根结点,然后前序遍历左子树,最后前序遍历右子树。
抽象表示:
void pre(Tree) //preOrder
{
Tree = Null return;
Tree.data //操作
pre(Tree.leftNode);
pre(Tree.rightNode);
}
前序遍历题目
2:中序遍历->左根右
规则如是二叉树为空,则返回空操作,然后中序遍历左子树,访问根结点,最后中序遍历右子树。
抽象表示:
void InO(Tree) //InOrder
{
Tree = Null return;
InO(Tree.leftNode);
Tree.data //操作
InO(Tree.rightNode);
}
中序遍历题目
3:后续遍历->左右根
规则如是二叉树为空,则返回空操作,然后后序遍历左子树,后序遍历右子树,最后访问根结点,
抽象表示:
void Pos(Tree) //PostOrder
{
Tree = Null return;
Pos(Tree.leftNode);
Pos(Tree.rightNode);
Tree.data //操作
}
后序遍历题目
4:层序遍历
借助其他数据结构,记录下,Tree的下一层的所有结点。这样一层一层的遍历。直到结束
抽象表示:
void Lev(Queue Tree) //levelOrder
{
while(Tree != NULL)
{
Tree.data //操作
Queue push Tree.leftNode;
Queue push Tree.rightNode;
Queue pop Tree;
}
}
层序遍历题目
构造二叉树的方法
根据树的遍历方法有3种,前序遍历,中序遍历,后序遍历
带来的构造二叉树的方法
分为[前序,中序],[前序,后序],[中序,后序]
1:[前序,中序]构造二叉树。
通过前序,确定每个根节点。前序第一个值为根结点。
通过根节点的值,查找中序,可以确定根结点。左子树结点和右子树结点数量
通过数组获取新的前序数组,后序数组,遍历左子树,右子树,完成构造。
抽象表示:
void bulidTree(root, Preorder,InOrder)
{
root = Preorder[0];
Preorder[0] find in InOrder = count;
leftNum = count;
newPreorder = Preorder[1,1+leftNum];
newInOrder = InOrder [0,leftNum];
bulidTree(root.leftNode, newPreorder,newInOrder);
free(newPreorder);
free(newInOrder);
rightNum = preorderSize - count - 1;
newPreorder = Preorder[count + 1,rightNum];
newInOrder = InOrder [count + 1,rightNum];
bulidTree(root.rightNode,newPreorder,newInOrder);
free(newPreorder);
free(newInOrder);
}
时间复杂度O(n)
空间复杂度O(n)
题目前中序构造二叉树
图片.png
2: [前序,后序]构造二叉树。 答案可能不唯一
通过前序,确定每个根节点。前序第一个值为根结点。
通过在后序中查找第二个值,来判断左右子树的长度
抽象表示:
void bulidTree(root, Preorder,PostOrder)
{
root = Preorder[0];
Preorder[1] find in PostOrder = count;
leftNum = count;
newPreorder = Preorder[1,1+leftNum];
newPostOrder= InOrder [0,leftNum];
bulidTree(root.leftNode, newPreorder,newPostOrder);
free(newPreorder);
free(newPostOrder);
rightNum = preorderSize - count - 1;
newPreorder = Preorder[count + 1,rightNum];
newPostOrder = InOrder [count, rightNum];
bulidTree(root.rightNode,newPreorder,newPostOrder);
free(newPreorder);
free(newPostOrder);
}
时间复杂度O(n)
空间复杂度O(n)
题目前后序构造二叉树
图片.png
3: [中序,后序]构造二叉树。
通过后序,确定每个根节点。后序最后一个值为根结点。
通过根节点的值,查找中序,可以确定根结点。左子树结点和右子树结点数量
通过数组获取新的中序数组,后序数组,遍历左子树,右子树,完成构造。
抽象表示:
void bulidTree(root, InOrder,PostOrder)
{
root = PostOrder[last];
PostOrder[0] find in InOrder = count;
leftNum = count;
newPostOrder = PostOrder[0,leftNum];
newInOrder = InOrder [0,leftNum];
bulidTree(root.leftNode, newInOrder,newPostOrder);
free(newPostOrder);
free(newInOrder);
rightNum = PostOrderSize - count - 1;
newPostOrder = PostOrder[count + 1,rightNum];
newInOrder = InOrder [count + 1,rightNum];
bulidTree(root.rightNode,newInOrder,newPostOrder);
free(newPostOrder);
free(newInOrder);
}
时间复杂度O(n)
空间复杂度O(n)
作者:goodgoodday
链接:https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-postorder-traversal/solution/gen-ju-qian-xu-he-hou-xu-bian-li-gou-zao-wq2v/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。