【Hot100】LeetCode—105. 从前序与中序遍历序列构造二叉树


1- 思路

递归

  • 前序:中左右
  • 中序:左中右

让前序的第一个元素作为中序的分割点
分割思路

  • 1- 递归参数与返回值(递归的指针是左闭右开的 也就是 [left,right) 的)
    • preOrder 前序数组;pLeft 中序数组左指针 用于切割;pRight:中序数组右指针 用于切割
    • inOrder前序数组;iLeft前序数组左指针 用于切割;iRight:前序数组右指针 用于切割
 TreeNode build(int[] preOrder,int pLeft,int pRight,int[] inOrder,int iLeft,int iRight)
  • 2- 终止条件
    • 两个 指针相遇时终止
  • 3- 树构造
  • 3.1 先找根:前序:中左右、中序:左中右,所以根节点一定是,前序数组的第一个元素
  • 3.2 去中序找 mid:用 iLeftiRight 去定位寻找,定位值为 mid
  • 3.3 中序数组拆分
    • iLfeft1 = iLfeft;
    • iRight1 = mid;
    • iLeft2 = mid+1;
    • iRight2 = iRight;
  • 3.4 前序数组拆分
    • pLeft1 = pLeft+1;
    • pRight1 = pLeft + (mid-iLeft1)+1;
    • pLeft2 = pRight1;
    • pRight2 = pRight;
  • 3.5 递归实现
    • 递归构造当前根节点的左子树和右子树
    • 左子树构造:root.left = build(preOrder,pLeft1,pRight1,inOrder,iLfeft1,iRight1);
    • 右子树构造:root.right = build(preOrder,pLeft2,pRight2,inOrder,iLfeft2,iRight2);

2- 实现

⭐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) {
        if(inorder.length==0){
            return null;
        }
        return build(preorder,0,preorder.length,inorder,0,inorder.length);
    }

    public TreeNode build(int[] preorder,int pLeft,int pRight,int[] inorder,int iLeft,int iRight){
        
        // 终止条件
        if(pLeft == pRight){
            return null;
        }
        
        // 找根
        int rootVal = preorder[pLeft];
        TreeNode root = new TreeNode(rootVal);

        // 定位mid
        int mid = 0;
        for(mid=iLeft ; mid<iRight;mid++){
            if(inorder[mid]==rootVal){
                break;
            }
        }

        // 拆中序
        int iLeft1 = iLeft;
        int iRight1 = mid;
        int iLeft2 = mid+1;
        int iRight2 = iRight;

        // 拆前序
        int pLeft1 = pLeft+1;
        int pRight1 = pLeft+(mid-iLeft1)+1;
        int pLeft2 = pRight1;
        int pRight2 = pRight;

        // 构造
        root.left = build(preorder,pLeft1,pRight1,inorder,iLeft1,iRight1);
        root.right = build(preorder,pLeft2,pRight2,inorder,iLeft2,iRight2);
        return root;
    }
}

3- ACM 实现

public class buildTree {

    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 TreeNode buildBy(int[] preOrder,int[] inOrder){
        // 调用递归build
        return build(preOrder,0,preOrder.length,inOrder,0,inOrder.length);
    }

    // 递归实现
    public static TreeNode build(int[] preOrder,int pLeft,int pRight,int[] inOrder,int iLeft,int iRight){
        //1. 终止条件
        if(pLeft==pRight){
            return null;
        }

        // 2. 构造根节点
        int rootVal = preOrder[pLeft];
        TreeNode root = new TreeNode(rootVal);

        // 3.定位mid
        int mid = 0;
        for(mid = iLeft;mid<iRight;mid++){
            if(inOrder[mid]==rootVal){
                break;
            }
        }

        // 拆分中序
        int iLeft1 = iLeft;
        int iRight1 = mid;
        int iLeft2 = mid+1;
        int iRight2 = iRight;

        // 拆分前序
        int pLeft1 = pLeft+1;
        int pRight1 = pLeft+(mid-iLeft1)+1;
        int pLeft2 = pRight1;
        int pRight2 = pRight;

        // 递归构造
        root.left = build(preOrder,pLeft1,pRight1,inOrder,iLeft1,iRight1);
        root.right = build(preOrder,pLeft2,pRight2,inOrder,iLeft2,iRight2);
        return root;
    }

    static List<List<Integer>> res = new ArrayList<>();
    public static List<List<Integer>> levelOrder(TreeNode root) {
        if(root==null){
            return res;
        }
        // 队列
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()){
            int len = queue.size();
            List<Integer> path = new ArrayList<>();
            while(len>0){
                TreeNode nowNode = queue.poll();
                path.add(nowNode.val);
                if(nowNode.left!=null) queue.offer(nowNode.left);
                if(nowNode.right!=null) queue.offer(nowNode.right);
                len--;
            }
            res.add(new ArrayList<>(path));
        }
        return res;
    }



    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        String[] pOrder =  sc.nextLine().replace("[","").replace("]","").split(",");
        String[] iOrder = sc.nextLine().replace("[","").replace("]","").split(",");
        int[] pNum = new int[pOrder.length];
        int[] iNum = new int[iOrder.length];
        for(int i = 0 ; i < pOrder.length;i++){
            pNum[i] = Integer.parseInt(pOrder[i]);
            iNum[i] = Integer.parseInt(iOrder[i]);
        }
        TreeNode root = buildBy(pNum,iNum);
        levelOrder(root);
        System.out.println("结果是"+res.toString());
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值