前序·中序
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
- 使用哈希表,构造哈希映射,快速定位根节点(省时)
- 前序遍历第一个节点即为根节点,对应找到中序遍历中根节点位置和左子树中节点数目
- 递归构造左右子树
/**
- Definition for a binary tree node.
- public class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
- TreeNode(int x) { val = x; }
- }
*/
class Solution {
Map<Integer,Integer> map;
public TreeNode buildTree(int[] preorder, int[] inorder) {
map=new HashMap<Integer,Integer>();
for(int i=0;i<preorder.length;i++){
//构造哈希映射,快速定位根节点
map.put(inorder[i],i);//键值对:键表示一个节点的值,值表示其在中序遍历中的出现位置。
}
return solve(preorder,inorder,0,preorder.length-1,0,preorder.length-1);
}
public TreeNode solve(int[] preorder,int[] inorder,int prel,int prer,int inl,int inr){
if(prel>prer){return null;}
int preroot=prel; //前序遍历中第一个位置就是根节点
int inroot=map.get(preorder[preroot]); //中序遍历中找到根节点位置
TreeNode root=new TreeNode(preorder[preroot]); //建立根节点
int len=inroot-inl; //左子树长度
//递归构造左右子树
root.left=solve(preorder,inorder,prel+1,prel+len,inl,inroot-1);
root.right=solve(preorder,inorder,prel+len+1,prer,inroot+1,inr);
return root;
}
}
中序·后序
根据一棵树的中序遍历与后序遍历构造二叉树。(无重复元素)
- 后序遍历最后一个元素即为根节点,由此在中序遍历中找到根节点位置
- 根据根节点位置将中序遍历分成左子树和右子树
- 递归构造左右子树
注意左右边界(当前位置+长度-1)
/**
- Definition for a binary tree node.
- public class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
- TreeNode(int x) { val = x; }
- }
*/
class Solution {
Map<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 solve(inorder,postorder,0,inorder.length-1,0,inorder.length-1);
}
public TreeNode solve(int[] inorder,int[] postorder,int inl,int inr,int postl,int postr){
if(postl>postr){return null;}
int postroot=postr; //后序遍历最后一个元素即为根节点
int inroot=map.get(postorder[postroot]); //在中序遍历中找到根节点位置
TreeNode root=new TreeNode(postorder[postroot]);
int len=inroot-inl;
//递归构造左子树·右子树
root.left=solve(inorder,postorder,inl,inroot-1,postl,postl+len-1);
root.right=solve(inorder,postorder,inroot+1,inr,postl+len,postr-1);
return root;
}
}
前序·后序
返回与给定的前序和后序遍历匹配的任何二叉树。pre 和 post 遍历中的值是不同的正整数。
- 前序第一个元素(后序最后一个节点)即为根节点
- 关键如何找到左子树的长度----(前序遍历中第二个元素在后序遍历中是左子树的根节点)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode constructFromPrePost(int[] pre, int[] post) {
return solve(pre,post,0,pre.length-1,0,pre.length-1);
}
public TreeNode solve(int[] pre,int[] post,int prel,int prer,int postl,int postr){
if(prel>prer){return null;}
TreeNode root=new TreeNode(pre[prel]); //前序遍历中第一个节点即为根节点
if(prel==prer){return root;} //只有一个节点时直接返回根
for(int i=postl;i<=postr;i++){
if(post[i]==pre[prel+1]){ //前序遍历第二个元素在后序遍历中为左子树的根节点
int len=i-postl+1; //由此求出左子树长度
root.left=solve(pre,post,prel+1,prel+len,postl,i);
root.right=solve(pre,post,prel+len+1,prer,i+1,postr-1);
return root;
}
}
return null;
}
}
返回与给定先序遍历 preorder 相匹配的二叉搜索树(binary search tree)的根结点。
- 先序遍历第一个元素就是根节点
- 左子树所有节点均小于根节点,右子树所有节点均大于根节点
/**
* 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 bstFromPreorder(int[] preorder) {
return solve(preorder,0,preorder.length-1);
}
public TreeNode solve(int[] preorder,int start,int end){
if(start>end){return null;}
TreeNode root=new TreeNode(preorder[start]); //先序序列第一个节点为根节点
int i=start+1;
//左子树所有节点小于根节点,右子树所有节点大于根节点
while(i<preorder.length && preorder[i]<root.val){i++;} //找到左子树范围
//递归构建左右子树
root.left=solve(preorder,start+1,i-1);
root.right=solve(preorder,i,end);
return root;
}
}