- Posted by 微博@Yangsc_o
- 原创文章,版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0
本题是leetcode,地址
题目
889. 根据前序和后序遍历构造二叉树
返回与给定的前序和后序遍历匹配的任何二叉树。
pre 和 post 遍历中的值是不同的正整数。
示例:
输入:pre = [1,2,4,5,3,6,7], post = [4,5,2,6,7,3,1]
输出:[1,2,3,4,5,6,7]提示:
1 <= pre.length == post.length <= 30
pre[] 和 post[] 都是 1, 2, ..., pre.length 的排列
每个输入保证至少有一个答案。如果有多个答案,可以返回其中一个。根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。例如,给出
105. 从前序与中序遍历序列构造二叉树
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/
9 20
/
15 7106. 从中序与后序遍历序列构造二叉树
根据一棵树的中序遍历与后序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。例如,给出
中序遍历 inorder = [9,3,15,20,7]
后序遍历 postorder = [9,15,7,20,3]
返回如下的二叉树:
3
/
9 20
/
15 7
分析
其实这三道题非常类似,做题的前提是需要了解树的前序遍历、中序遍历、后续遍历的特点;
- 前序遍历:遍历顺序,根-左-右;第一个节点就是根节点;
- 中序遍历:遍历顺序,左-根-右;根节点是区分左右子树的节点;
- 后续遍历:遍历顺序,左-右-根;由此可知,根节点在最后;
[889. 根据前序和后序遍历构造二叉树]:
根据前序遍历和后序遍历特点,我们找到前序遍历中的第一个非根节点在第二个节点的位置,就可以分别分离出:前序遍历:(根)(左子树)(右子树)和 (左子树)(右子树)(根),这样我们便得到一个根节点,分别对左子树和右子树进行递归操作,也可以分别获取到其根节点,如此便可得到一颗完整的树;
同理我们可以分析出 前+中;中+后的推断逻辑;
一位网友概括如下:
前+后
首先我们可以显然知道当前根节点为pre[pre_start],并且它在后序中的位置为post_end,因此这里我们需要找到能区分左右子树的节点。
我们知道左子树的根节点为pre[pre_start+1],因此只要找到它在后序中的位置就可以分开左右子树(index的含义)
前+中
首先我们可以显然知道当前根节点为pre[pre_start],只用找出它在中序中的位置,就可以把左右子树分开(index的含义)
中+后
首先我们可以显然知道当前根节点为post[post_end],只用找出它在中序中的位置,就可以把左右子树分开(index的含义)
code
// 889. 根据前序和后序遍历构造二叉树
public TreeNode constructFromPrePost(int[] pre, int[] post) {
if(pre==null || pre.length==0) {
return null;
}
TreeNode root = new TreeNode(pre[0]);
int length = pre.length;
if(length == 1) {
return root;
}
for(int index =0; index < length; index ++) {
if(pre[1] == post[index]) {
int[] pre_left = Arrays.copyOfRange(pre,1,index + 1 + 1);
int[] pre_right = Arrays.copyOfRange(pre,index + 1 + 1 ,length);
int[] post_left = Arrays.copyOfRange(post,0,index);
int[] post_right = Arrays.copyOfRange(post,index + 1, length -1);
root.left = constructFromPrePost(pre_left,post_left);
root.right = constructFromPrePost(pre_right,post_right);
break;
}
}
return root;
}
// 105. 从前序与中序遍历序列构造二叉树
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder == null || preorder.length == 0) {
return null;
}
int length = preorder.length;
TreeNode root = new TreeNode(preorder[0]);
if(length == 1) {
return root;
}
for(int index = 0; index < length; index ++) {
if(root.val == inorder[index]) {
int[] preorder_left = Arrays.copyOfRange(preorder,1,index + 1);
int[] preorder_right = Arrays.copyOfRange(preorder,index + 1, length);
int[] inorder_left = Arrays.copyOfRange(inorder,0,index);
int[] inorder_right = Arrays.copyOfRange(inorder,index + 1,length);
root.left = buildTree(preorder_left,inorder_left);
root.right = buildTree(preorder_right,inorder_right);
break;
}
}
return root;
}
// 106. 从中序与后序遍历序列构造二叉树
public TreeNode buildTree(int[] inorder, int[] postorder) {
if(postorder == null || postorder.length == 0) {
return null;
}
int length = postorder.length;
if(length == 1){
return new TreeNode(postorder[length -1]);
}
TreeNode root = new TreeNode(postorder[length - 1]);
for(int index = 0; index < length; index ++) {
if(postorder[length -1] == inorder[index]) {
int[] inorder_left = Arrays.copyOfRange(inorder,0,index);
int[] inorder_right = Arrays.copyOfRange(inorder,index + 1,length);
int[] postorder_left = Arrays.copyOfRange(postorder,0,index);
int[] postorder_right = Arrays.copyOfRange(postorder,index,length -1);
root.left = buildTree(inorder_left,postorder_left);
root.right = buildTree(inorder_right,postorder_right );
break;
}
}
return root;
}