剑指offer java版 test4—重建二叉树

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

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        
    }
}

2.基础知识复习
2.1 树:每个节点最多有两个子树的树结构。

2.1 二叉树:二叉树是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树组成。

2.3 二叉树的特点::
1)每个结点最多有两颗子树,所以二叉树中不存在度大于2的结点。
2)左子树和右子树是有顺序的,次序不能任意颠倒。
3)即使树中某结点只有一棵子树,也要区分它是左子树还是右子树。

2.4 二叉树的存储结构:
二叉树有顺序存储和二叉链表存储两种方式。
2.4.1 顺序存储
二叉树的顺序存储结构就是使用一维数组存储二叉树中的结点,并且结点的存储位置,就是数组的下标索引。
在这里插入图片描述
上图所示的二叉树,采用顺序存储方式时,如下图:
在这里插入图片描述
那么当二叉树为不完全二叉树时呢,其顺序存储的结构形式如下:
在这里插入图片描述
其中,浅色表示结点不存在,那么上图二叉树的顺序存储结构如图:在这里插入图片描述^表示数组种此位置没有存储结点,由此可以发现,顺序存储结构中已经出现了空间浪费的情况。所以可以考虑采用链式存储。

2.4.2二叉链表存储
二叉树每个结点最多有两个孩子,刚好与链表对应,因此可以将结点数据结构定义成为一个数据和两个指针域。表示方法如下图:
在这里插入图片描述
其表示如下图所示:
在这里插入图片描述
2.5 二叉树的遍历(考点)
二叉树的遍历是指从二叉树的根结点出发,按照某种次序依次访问二叉树中的所有结点。
二叉树的访问次序分为四种:前序遍历,中序遍历,后序遍历,层序遍历。

2.5.1 前序遍历: 从二叉树的根结点出发,当第一次到达结点时就输出结点数据,按照先向左在向右的方向访问。
其输出结果为:ABDHIEJCFG

2.5.2 中序遍历:从二叉树的根结点出发,当第二次到达结点时就输出结点数据,按照先向左在向右的方向访问。
其输出结果为:HDIBJEAFCG
其具体访问顺序为:
(从根结点出发,则第一次到达结点A,不输出A,继续向左访问,第一次访问结点B,不输出B;继续到达D,H;
到达H,H左子树为空,则返回到H,此时第二次访问H,故输出H
H右子树为空,则返回至D,此时第二次到达D,故输出D;
由D返回至B,第二次到达B,故输出B;
按照同样规则继续访问,输出J、E、A、F、C、G;)

2.5.3 后序遍历:从二叉树的根结点出发,当第三次到达结点的时候就输出结点数据,按照从左到右的方向访问。
其输出结果为:HIDJEBFGCA

2.5.4 层次遍历:层次遍历就是按照树的层次自上而下的遍历二叉树。

3. 二叉树的重建

依据前序 中序 后序遍历的特点:
前序遍历:根结点 —> 左子树 —> 右子树
中序遍历:左子树—> 根结点 —> 右子树
后序遍历:左子树 —> 右子树 —> 根结点

笔算时(推完后才发现,由前序遍历可知1为根节点,那么由中序遍历可知,472为1的左子树,5386为右子树,关同理,关于472,可知2为根结点,4为2的左子树,7为4的右子树…),依据题目给的前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},依据前序遍历,可知1为第一层的根节点,且1有左子树和右子树,且2为1的左子树;那么还是依据中序遍历和前序遍历,可得4为2的左子树(前序遍历序列中4在2的后面,中序遍历序列中,4在2的前面),又因为,前序和中序遍历序列中,7均在4的后面,所以7为4的右子树。同理慢慢推得原始的二叉树为:
在这里插入图片描述

所以,我们可以利用前序遍历序列找根节点, 再通过中序遍历,找到左子树和右子树。,代码利用递归来解决。思路:比如先通过前序遍历序列找到根节点1,通过中序遍历得到1的左子树{4 2 7},那么将{2 4 7}和{4 2 7}作为新的前序和中序,再调用函数,…后面同理。
最终思路如下(参考别人的):
在这里插入图片描述
代码如下:

package cn.test4;
import java.util.Arrays;

public class TreeTest {
    public static void main(String[] args){
        int [] pre={1,2,4,7,3,5,6,8};
        int [] in={4,7,2,1,5,3,8,6};
        Solution solution=new Solution();
        solution.reConstructBinaryTree(pre,in);
        
    }
}

class Solution{
    public TreeNode reConstructBinaryTree(int [] pre,int [] in){
        if(pre.length==0){
            return null;
        }

        TreeNode root=new TreeNode(pre[0]);

        for(int i= 0; i<in.length; i++){
            if(pre[0]==in[i]){
                root.left= reConstructBinaryTree(Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(in,0,i));
                root.right=reConstructBinaryTree(Arrays.copyOfRange(pre,i+1,pre.length),Arrays.copyOfRange(in,i+1,in.length));
                break;
            }
        }

        return root;
    }
 }

发布了10 篇原创文章 · 获赞 0 · 访问量 72

猜你喜欢

转载自blog.csdn.net/weixin_42146993/article/details/104750269