【算法训练】LeetCode#105 从前序与中序遍历序列构造二叉树

一、描述

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

给定两个整数数组 preorderinorder ,其中 preorder 是二叉树的先序遍历inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例 1:

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

示例 2:

输入: preorder = [-1], inorder = [-1]
输出: [-1]

二、思路

光根据一个遍历序是无法确定唯一树的,所以这道题是根据前和中序构造。初步想法是根据前序的根节点对中序遍历上的节点做划分,能够区分出其余节点在左子树还是右子树,然后对于子树再进行相同操作。(没把握却一次过..)

三、解题

public static 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;
    }
}
public static class Solution {
    int preLoc = -1;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if (preorder == null || inorder == null || preorder.length < 1 || inorder.length < 1){
            return null;
        }
        return process(preorder,inorder,0,inorder.length-1,findRoot(preorder,inorder,0,inorder.length-1));
    }

    public TreeNode process(int[] preorder,int[] inorder,int inLeftLoc,int inRightLoc,int root){
        if (inLeftLoc > inRightLoc){
            return null;
        }
        if (inLeftLoc == inRightLoc){
            // 范围上只有一个节点
            return new TreeNode(inorder[inLeftLoc]);
        }
        TreeNode node = new TreeNode(inorder[root]); // 根节点
        node.left = process(preorder,inorder,inLeftLoc,root-1,findRoot(preorder,inorder,inLeftLoc,root-1));
        node.right = process(preorder,inorder,root+1,inRightLoc,findRoot(preorder,inorder,root+1,inRightLoc));
        return node;
    }

    // 返回当前先序遍历中的位置就是接下来的根节点(根据先序遍历的特点)
    public int findRoot(int[] preorder,int[] inorder,int leftLoc,int rightLoc){
        if (leftLoc > rightLoc){
            return -1;
        }
        int val = preorder[++this.preLoc]; // 得到下一个根节点的值
        int ans = 0;
        for (int i = leftLoc ; i <= rightLoc ; i++){
            // 在给定范围上找到中序遍历中根节点位置
            if (inorder[i] == val){
                ans = i;
                break;
            }
        }
        return ans;
    }
    
    
    // 因为节点不重复,所以每次找寻root节点时可以用map进行优化
    public TreeNode buildTreeV2(int[] preorder, int[] inorder) {
        if (preorder == null || inorder == null || preorder.length < 1 || inorder.length < 1){
            return null;
        }
        int n = preorder.length;
        indexMap = new HashMap<Integer, Integer>();
        for (int i = 0; i < n; i++) {
            indexMap.put(inorder[i], i); // 根据根节点的值知道inorder中根节点位置
        }

        return process(preorder,inorder,0,inorder.length-1,indexMap.get(preorder[++preLoc]));
    }

    public TreeNode processV2(int[] preorder,int[] inorder,int inLeftLoc,int inRightLoc,int root){
        if (inLeftLoc > inRightLoc){
            --preLoc;
            return null;
        }
        if (inLeftLoc == inRightLoc){
            // 范围上只有一个节点
            return new TreeNode(inorder[inLeftLoc]);
        }
        TreeNode node = new TreeNode(inorder[root]); // 根节点

        node.left = preLoc == indexMap.size()-1 ? null : process(preorder,inorder,inLeftLoc,root-1,indexMap.get(preorder[++preLoc]));
        node.right = preLoc == indexMap.size()-1 ? null : process(preorder,inorder,root+1,inRightLoc,indexMap.get(preorder[++preLoc]));
        return node;
    }
}
posted @ 2023-01-12 14:44  小拳头呀  阅读(8)  评论(0编辑  收藏  举报