根据前序遍历和中序遍历的结果重构二叉树LeetCode 95

题目描述

https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
根据一棵树的前序遍历与中序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

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

    3
   / \
  9  20
    /  \
   15   7

思路

首先我们在上一篇文章中解释了前序遍历和中序遍历的含义,因为是树的结构,一般都是用递归来实现。

  • 用数学归纳法的思想就是,假设最后一步,就是root的左右子树都已经重建好了,那么我只要考虑将root的左右子树安上去即可。
  • 根据前序遍历的性质,第一个元素必然就是root,那么下面的工作就是如何确定root的左右子树的范围。
  • 根据中序遍历的性质,root元素前面都是root的左子树,后面都是root的右子树。那么我们只要找到中序遍历中root的位置,就可以确定好左右子树的范围。

简单来说就是当前前序遍历的结果,第一个元素必然是当前节点的值,而对于中序遍历来说,当前节点值的位置的前面都是左子树的值,后面都是右子树的值,所以根据这个思想,重新构建二叉树。

实现代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    public TreeNode build(int[] pre,int[] ino){
        if(ino.length == 0 || pre.length == 0)
            return null;
        int i = 0,target = pre[0];//target 是前序遍历的第一个元素,即当前节点的值
        for(;i < ino.length;i++){
            if(ino[i] == target) //在中序遍历的数组中找到当前节点的位置,这样就可以区分当前节点的左子树和右子树
                break;
        }
        TreeNode node = new TreeNode(ino[i]); // ino[i]是当前节点
        node.left = build(Arrays.copyOfRange(pre,1,i+1),Arrays.copyOfRange(ino,0,i));
        //Arrays.copyOfRange(),是一个左闭右开的,当前节点的左子树的长度为i,所以将当前节点的左子树的前序遍历数组和中序遍历数组传入。
        node.right = build(Arrays.copyOfRange(pre,i+1,pre.length),Arrays.copyOfRange(ino,i+1,ino.length));
        return node;
    }

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return build(preorder,inorder);
    }
}

发布了18 篇原创文章 · 获赞 2 · 访问量 382

猜你喜欢

转载自blog.csdn.net/weixin_40907792/article/details/104060610