leecode 105. 从前序与中序遍历序列构造二叉树

这篇博客介绍了如何通过给定的前序遍历和中序遍历序列来构建二叉树。首先,博主提出了一个递归的解决方案,然后针对中序遍历查找根节点的过程进行了优化,使用哈希映射存储中序遍历的节点位置,以减少复杂度。优化后的算法能更高效地构建二叉树。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 105. 从前序与中序遍历序列构造二叉树

        这个图表明了这个二叉树的遍历顺序,但是下标是按照左闭右闭原则,我的做法是左闭右开

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

递归:

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

    private TreeNode buildTree1(int[] preorder, int preleft, int preright, int[] inorder, int inleft, int inright) {
        if (preright - preleft < 1 || inright - inleft < 1) return null;
        if (preright - preleft == 1) return new TreeNode(preorder[preright - 1]);
        int rootVal = preorder[preleft];
        TreeNode root = new TreeNode(rootVal);
        int index = 0;
        for (int i = inleft; i < inright; i ++) {
            if (inorder[i] == rootVal) {
                index = i;
                break;
            }
        }
//这是原来的值,和答案相同,但是答案按照左闭右闭原则,即
//buildTree1(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
//因此需要preleft + index - inleft在原下标基础上+1,其他同leecode 104题
        //root.left = buildTree1(preorder, preleft + 1, preleft + 1 + index - inleft,inorder, inleft, inleft + index);
        root.left = buildTree1(preorder, preleft + 1, preleft + index - inleft + 1,inorder, inleft, index);
        root.right = buildTree1(preorder, preleft + 1 + index - inleft, preright,inorder, index + 1, inright);
        return root;
    }
}

         优化方案:本题中,在中序数组中查找根节点的这个过程中套用了for循环,使复杂度增加,可以使用hashmap提前存储中序数组,需要的时候直接拿来用就可以了,这样可以降低复杂度。代码如下:


优化版本:

class Solution {
    private Map<Integer, Integer> indexMap;
//优化版需要使用Map,所以方法中需要带上
    public TreeNode myBuildTree(int[] preorder, int[] inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {
        if (preorder_left > preorder_right) {
            return null;
        }

        // 前序遍历中的第一个节点就是根节点
        int preorder_root = preorder_left;
        // 在中序遍历中定位根节点
        int inorder_root = indexMap.get(preorder[preorder_root]);
        
        // 先把根节点建立出来
        TreeNode root = new TreeNode(preorder[preorder_root]);
        // 得到左子树中的节点数目
        int size_left_subtree = inorder_root - inorder_left;
        // 递归地构造左子树,并连接到根节点
        // 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
        root.left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1);
        // 递归地构造右子树,并连接到根节点
        // 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
        root.right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);
        return root;
    }

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        int n = preorder.length;
        // 构造哈希映射,帮助我们快速定位根节点
        indexMap = new HashMap<Integer, Integer>();
        for (int i = 0; i < n; i++) {
            indexMap.put(inorder[i], i);
        }
        return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值