重建二叉树

1. 题目概述

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

例如,给出

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7
限制:0 <= 节点个数 <= 5000

2. 题目分析

首先,这道题目考察的是二叉树的基本知识。前序遍历即就是先打印根,再打印左右节点。中序遍历是先打印左节点,再打印根节点,最后打印右节点。给出了前序遍历和中序遍历,需要构建出二叉树。首先,我的大方向思路是这样的:

1. 在前序遍历中找到第一个数据,就是根节点。
       2. 在中序遍历中找到这个节点,分别推出它的左孩子和右孩子。
       3. 以此类推,直到结束。

总体是以前序遍历的思想进行切入,我画了一张图描述了其过程:

3. 解题代码

class Solution {
    int preIndex= 0;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder == null || inorder == null || preorder.length == 0 || inorder.length == 0) {
            return null;
        }
      return buildTreeChild(preorder, inorder, 0, inorder.length-1);
    }

    public TreeNode buildTreeChild(  int[] preorder,int[] inorder,int inbegin, int inend) {
    //终止条件 判断是否有左树或者右树
    if (inbegin > inend) {
        return null;
    }
    //在前序遍历中new 根节点
    TreeNode root = new TreeNode(preorder[preIndex]);
     //在中序遍历找到pi所在下标元素
     int rootIndex = findIndexOfInorder(inorder, inbegin, inend, preorder[preIndex]);
     preIndex++;
     root.left = buildTreeChild(preorder, inorder, inbegin, rootIndex-1);
     root.right = buildTreeChild(preorder, inorder, rootIndex+1, inend);
     return root;
    }

    private int findIndexOfInorder(int[] inorder, int inbegin, int inend, int val) {
    for (int i = inbegin; i <= inend; i++) {
        if (inorder[i] == val) {
            return i;
        }
    }
    return -1;
    }
}

4. 思考总结

由于二叉树的结构所致,二叉树的大部分题目都是要用递归来写的。而切入点就是二叉树的四种遍历,前序遍历,中序遍历,后序遍历和层序遍历,因此熟练掌握四种遍历方式是非常必要的。

其实,也可以根据后序遍历和中序遍历构建二叉树道理相同,和前序遍历一样,只是传入参数和遍历顺序不同。就不详细写了呦,附上代码一只:

public int postIndex = 0;
public TreeNode buildTreeChild(int[] inorder, int[] postorder,int inbegin, int inend) {

    //终止条件 判断是否有左树或者右树
    if (inbegin > inend) {
        return null;
    }

    //new 根节点
    TreeNode root = new TreeNode(postorder[postIndex]);

    //在中序遍历找到pi所在下标元素
    int rootIndex = findIndexOfInorder(inorder, inbegin, inend, postorder[postIndex]);
    postIndex--;
    root.right = buildTreeChild(inorder,postorder, rootIndex+1,inend);
    root.left = buildTreeChild(inorder, postorder, inbegin,rootIndex-1);
    return root;
}

private int findIndexOfInorder(int[] inorder, int inbegin, int inend, int val) {
    for (int i = inbegin; i <= inend; i++) {
        if (inorder[i] == val) {
            return i;
        }
    }
    return -1;
}

public TreeNode buildTree(int[] inorder, int[] postorder) {
    if (postorder == null || inorder == null) {
        return null;
    }
    if (postorder.length == 0 || inorder.length == 0) {
        return null;
    }

    postIndex = postorder.length-1;
    return buildTreeChild(inorder, postorder, 0, inorder.length-1);
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值