二叉树重建 剑指offer07
题目
思路
首先就是根据前序和中序的特点,前序是先遍历根节点,然后是遍历左子树、再遍历右子树(这个很重要)这样就是可以对前序遍历分为三个部分根节点、左子树、右子树,中序遍历是根据前序遍历的跟节点进行划分,分为左子树、根节点、右子树,这个是递归传递参数的需要用到的条件。
每次在前序找到根节点、然后到中序遍历就可以根据找到的根节点将树分为左右子树。
递归结束条件 前序遍历的数组小于0或者中序遍历的数组小于0 判断一个就可以 ,一样的。
代码
/**
* 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;
}
return helper(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
}
//递归
public TreeNode helper(int[] preorder,int preL,int preR,int[] inorder,int inoL,int inoR){
//最后一次的条件
if(preR - preL<0){return null;}
//根节点
int rootV = preorder[preL];
//在中序中找到这个节点
int no = inoL;
for(;no<=inoR;no++){
if(inorder[no] == rootV){
break;
}
}
TreeNode root = new TreeNode(rootV);
//因为前序遍历是先遍历左右,然后遍历右边 所以前序遍历里面 第一个是根节点,然后是一块左子树 最后是一块右子树
root.left= helper(preorder,preL+1,preL+no-inoL,inorder,inoL,no-1);
root.right=helper(preorder,preL+no-inoL+1,preR,inorder,no+1,inoR);
return root;
}
}
题目变种—根据后序遍历和中序遍历重建二叉树
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
后序遍历是 9,15,7,20,3
取最后一个节点3,在中序中 划分出 9 和15,20,7
同样根据划分特点 后续的特点是 左子树,右子树,根节点后序遍历中,可以分出来9和15,7,20,将他们进行递归。和之前不同仅仅只是取第一个还是最后一个节点
代码
//preorder是后序遍历的数组
public TreeNode helper(int[] preorder,int preL,int preR,int[] inorder,int inoL,int inoR){
//最后一次的条件
if(preR - preL<0){return null;}
//根节点 从最后取
int rootV = preorder[preR];
//在中序中找到这个节点
int no = inoL;
for(;no<=inoR;no++){
if(inorder[no] == rootV){
break;
}
}
TreeNode root = new TreeNode(rootV);
//主要找到这两行怎么传参
//preL+no-inoL-1这里是从preL的位置开始 找左子树数量的位置 no-inoL如果是1,就是只有一个数,preL本身就是1了 所以要-1.no-1是因为no这个数是根节点 不需要加入
root.left= helper(preorder,preL,preL+no-inoL-1,inorder,inoL,no-1);
root.right=helper(preorder,preL+no-inoL,preR-1,inorder,no+1,inoR);
return root;
}