LeetCode-从前序遍历和中序遍历构造二叉树

一、题目

给定一棵树的前序遍历 preorder 与中序遍历  inorder。请构造二叉树并返回其根节点。

例如:preorder = [3,9,20,15,7], inorder = [9,3,15,20,7],得到如下二叉树。

1、分析

通过前序遍历和中序遍历构建二叉树的原理就不说了,都是基础。说说怎么用代码的方式构造二叉树。

一开始想到用队列能不能实现,发现写起来太复杂了,还是用递归+partition。

首先看前序遍历数组,第一个数就是当前需要构造的根节点【3】,于是在中序遍历数组中找到这个节点。于是就可以将中序遍历数组分为三部分:①左子树【9】②根结点【3】③右子树【15,20,7】。要得到左子树的根结点,递归查找左子树部分;得到右子树的根结点,递归查找右子树部分。当元素用完时,查找结束。

2、代码

class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return helper(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
    }

    public TreeNode helper(int[] preorder,int preStart,int preEnd,int[] inorder,int inStart,int inEnd){
        if(preStart > preEnd || inStart > inEnd) return null;
        //当前根节点
        TreeNode root = new TreeNode(preorder[preStart]);
        //找到中序遍历中根结点的下标
        int index = inStart;
        for(int i = inStart; i <= inEnd; i++){
            if(root.val == inorder[i]) index = i;
        }
        //求左子树长度
        int leftChildLength = index - inStart;
        //关键点在于划分好左右子树的下标范围
        //递归求解左子树根结点
        root.left = helper(preorder,preStart+1,preStart+leftChildLength,inorder,inStart,index-1);
        //递归求解右子树根结点
        root.right = helper(preorder,preStart+leftChildLength+1,preEnd,inorder,index+1,inEnd);
        return root;
    }
}

二、题目变形

从中序遍历与后序遍历序列中构造二叉树

原理是一样的,递归+partition,划分好左右子树的区间即可。

class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        return helper(inorder,0,inorder.length-1,postorder,0,postorder.length-1);
    }

    public TreeNode helper(int[] inorder,int inStart,int inEnd,int[] postorder,int postStart,int postEnd){
        if(inStart > inEnd || postEnd < postStart) return null;
        TreeNode root = new TreeNode(postorder[postEnd]);
        //找到右子树长度
        int index = inEnd;
        for(int i = inEnd; i >= inStart; i--){
            if(inorder[i] == root.val) index = i;
        }
        int rightChildLength = inEnd - index;
        root.right = helper(inorder,index+1,inEnd,postorder,postEnd-rightChildLength,postEnd-1);
        root.left = helper(inorder,inStart,index-1,postorder,postStart,postEnd-rightChildLength-1);
        return root;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值