二叉树各种遍历真的很难?大sai带你拿捏!(三)
给两个序列如何构造一棵二叉树
经常会遇到给两个序列确定一个二叉树,当然这个序列其中之一必须包含中序遍历序列。前序、中序确定二叉树和后序、中序确定一个二叉树的原理一致。
前序中序确定一棵二叉树
根据一棵树的前序遍历与中序遍历构造二叉树。当然也是力扣105的原题。
注意:你可以假设树中没有重复的元素。
分析:
给定一个前序序列和一个中序序列,且里面没有重复的元素,如何构造一棵二叉树呢?我们可以先单独观察两个序列的特征:
前序遍历:遍历规则为(根,[左侧区域],[右侧区域])。
中序遍历:遍历规则为([左侧区域],根,[右侧区域])。
其中前序遍历的左侧区域和中序遍历的左侧区域包含元素的范围相同,根也是相同的。所以可以进行这样的操作:
- 根据前序遍历的第一个找到根节点,可以确定根。
- 通过中序遍历找到根节点的值,这样可以知道左侧区域和右侧区域节点个数多少。
- 根节点左侧区域由前中序列确定的左侧区域确定,根节点的右侧节点由前中序序列的右侧区域确定。
一些操作可以借助这张图进行理解:
具体的实现上,可以使用一个HashMap存储中序存储的序列,避免重复计算。实现的代码为:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder.length==0)
return null;
TreeNode root=new TreeNode(preorder[0]);
Map<Integer, Integer>map=new HashMap<Integer, Integer>();
for(int i=0;i<inorder.length;i++)
{
map.put(inorder[i], i);
}
return buildTree(preorder,0,preorder.length-1, map,0,inorder.length-1);
}
private TreeNode buildTree(int[] preorder, int preStart, int preEnd, Map<Integer, Integer> map, int inStart, int inEnd) {
// TODO Auto-generated method stub
if(preEnd<preStart||inEnd<inStart)
return null;
TreeNode node=new TreeNode(preorder[preStart]);
int i=map.get(preorder[preStart]);//节点的值
int leftlen=i-inStart;//左面的长度
node.left=buildTree(preorder, preStart+1, preStart+1+leftlen, map, inStart, i-1);
node.right=buildTree(preorder, preStart+leftlen+1,preEnd, map, i+1, inEnd);
return node;
}
}
中序后序确定一个二叉树
根据一棵树的中序遍历与后序遍历构造二叉树,力扣106题
注意:你可以假设树中没有重复的元素。
例如,给出
中序遍历 inorder = [9,3,15,20,7]
后序遍历 postorder = [9,15,7,20,3]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
分析:
有了上面的分析,那么通过一个后序遍历和中序遍历去构造一棵二叉树,其实原理和前面的也是一样的。
后序遍历:遍历规则为([左侧区域],[右侧区域],根)。
中序遍历:遍历规则为([左侧区域],根,[右侧区域])。
具体实现的代码为:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode buildTree(int[] inorder,int[] postorder) {
if(postorder.length==0)
return null;
Map<Integer, Integer>map=new HashMap<Integer, Integer>();
for(int i=0;i<inorder.length;i++)
{
map.put(inorder[i], i);
}
return buildTree(postorder,0,postorder.length-1, map,0,inorder.length-1);
}
private TreeNode buildTree(int[] postorder, int postStart, int postEnd, Map<Integer, Integer> map, int inStart, int inEnd) {
// TODO Auto-generated method stub
if(postEnd<postStart||inEnd<inStart)
return null;
TreeNode node=new TreeNode(postorder[postEnd]);
int i=map.get(postorder[postEnd]);
int leftlen=i-inStart;
node.left=buildTree(postorder, postStart,postStart+leftlen-1, map, inStart, i-1);
node.right=buildTree(postorder, postStart+leftlen,postEnd-1, map, i+1, inEnd);
return node;
}
}
结语
好了,今天到这里就先介绍完了,但二叉树的内容远不止于此,还有非常牛批的Morris遍历,以及一些二叉树骚操作技巧常考问题后面还会慢慢总结分享给大家。
原创不易,如果本文对你有帮助,还请动动小手,帮忙点个赞和在看,分享给好友或者朋友圈,谢谢啦!
文章转自公众号:bigsai