重做剑指offer(四)——重建二叉树

重做剑指offer(四)——重建二叉树


题目描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

分析:改题是给出二叉树的前序遍历序列和中序遍历序列,编写函数实现重建二叉树的功能。既然如此,我们就必须先要知道啥是二叉树的前序遍历,啥又是中序遍历。

前序遍历:先访问二叉树的根节点,再访问左子节点,最后访问右子节点;
中序遍历:先访问二叉树的左子节点,再访问根节点,最后访问右子节点;
后序遍历:先访问二叉树的左子节点,再访问右子节点,最后访问根节点。
递归代码实现如下:

//中序遍历
public void infixOrder(Node current){
    if(current != null){
        infixOrder(current.leftChild);
        System.out.print(current.data+" ");
        infixOrder(current.rightChild);
    }
}
 
//前序遍历
public void preOrder(Node current){
    if(current != null){
        System.out.print(current.data+" ");
        preOrder(current.leftChild);
        preOrder(current.rightChild);
    }
}
 
//后序遍历
public void postOrder(Node current){
    if(current != null){
        postOrder(current.leftChild);
        postOrder(current.rightChild);
        System.out.print(current.data+" ");
    }
}

(上面关于前序遍历、中序遍历、后序遍历的知识摘抄自博客
也就是说,前序遍历的第一个元素与后序遍历的最后一个元素,是这棵树的根节点,然后再在中序遍历中找到这个元素,这个元素之前的元素就是该树的左子树,之后的元素是该树的右子树,区分开左右两棵子树后,再分别找到两子树的根节点,重复以上步骤,就能重建二叉树,实现代码如下:

import java.util.*;
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        if(pre.length == 0||in.length == 0)
            return null;
        int L = pre.length;
        TreeNode node = new TreeNode(pre[0]);
        for(int i = 0;i < L;i++){
            if(pre[0] == in[i]){					//这个判断书在找根节点
                node.left = reConstructBinaryTree(Arrays.copyOfRange(pre,1,i + 1),Arrays.copyOfRange(in,0,i));
                node.right = reConstructBinaryTree(Arrays.copyOfRange(pre,i + 1,L),Arrays.copyOfRange(in,i + 1,L));
            }
        }
        return node;
    }
}

知识点总结:如果是C/C++,可以很方便地使用指针把数组中的部分元素给提取出来,但是在JAVA中不能直接使用指针,如果一定要在函数中使用数组送的子数组,一种方法是自己编写一个函数,在形参中规定数组的起点和终点,如下(这个是在牛客网上直接copy过来的):

public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);
        return root;
    }
    //前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}
    private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) {
         
        if(startPre>endPre||startIn>endIn)
            return null;
        TreeNode root=new TreeNode(pre[startPre]);
         
        for(int i=startIn;i<=endIn;i++)
            if(in[i]==pre[startPre]){
                root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
                root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);
                      break;
            }
                 
        return root;
    }
}

当然第二种方法是调用JAVA自带的函数Arrays.copyOfRange,调用格式如下

Arrays.copyOfRange(int[] original, int from, int to);

有以下规则
第一个参数original表示源数组;
第二个参数from表示开始位置(也就是起点元素的下标,可以从0开始,该元素取得到);
第三个参数to表示结束位置(该元素取不到)。

猜你喜欢

转载自blog.csdn.net/biandi9300/article/details/89302851