zoukankan      html  css  js  c++  java
  • [leetCode]106. 从中序与后序遍历序列构造二叉树

    博客园:https://blog.csdn.net/renweiyi1487/article/details/109321267

    题目

    链接:https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal

    根据一棵树的中序遍历与后序遍历构造二叉树。

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

    例如,给出
    
    中序遍历 inorder = [9,3,15,20,7]
    后序遍历 postorder = [9,15,7,20,3]
    返回如下的二叉树:
    
        3
       / 
      9  20
        /  
       15   7
    

    非索引版好理解

    思路: 已知一棵树的后序遍历那么很容易找到根节点,也就是后续遍历数组中的最后一个节点。以该节点为切割点,在前序遍历数组中进行切割,将前序遍历数组切割成左右两部分,这里需要注意循环不变量原则也就是要确定切割区间的开闭状态保持不变! 前序遍历数组切割完成后根据切割后的左右子数组的长度切割后续遍历数组,这样就得到了左中序遍历数组---左后续遍历数组右中序遍历数组----右后续遍历数组。这样就可以递归解决了,递归需要确定退出条件,当后数组长度为0时说明是空节点直接返回空,如果数组长度为1则说明是叶子节点直接返回该结点。

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        public TreeNode buildTree(int[] inorder, int[] postorder) {
            if (inorder.length == 0 || postorder.length == 0)
                return null;
            return traversal(inorder, postorder);
        }
    
        private TreeNode traversal(int[] inorder, int[] postorder) {
            // 第一步,如果数组大小为0说明是空节点了
            if (inorder.length == 0) return null;
            // 第二步,如果不为空取后续遍历数组作为节点元素
            int rootValue = postorder[postorder.length - 1];
            TreeNode root = new TreeNode(rootValue);
            // 叶子节点
            if (postorder.length == 1) return root;
            // 第三步, 查找切割点
            int delimiterIndex;
            for (delimiterIndex = 0; delimiterIndex < inorder.length; delimiterIndex++) {
                if (inorder[delimiterIndex] == rootValue) break;
            }
            // 第四步,切割中序遍历数组坚持左闭右开原则
            int[] leftInorder = Arrays.copyOfRange(inorder, 0, delimiterIndex);
            // System.out.println(delimiterIndex + 1 + " " + inorder.length);
            // System.out.println(Arrays.toString(inorder));
            int[] rightInorder = Arrays.copyOfRange(inorder, delimiterIndex + 1, inorder.length); 
            // System.out.println(Arrays.toString(rightInorder));
            // 第5步,切割后续遍历数组 
            int[] leftPostorder = Arrays.copyOfRange(postorder, 0, leftInorder.length);
            int[] rightPostorder = Arrays.copyOfRange(postorder, leftInorder.length, postorder.length - 1);
            // 第六步,递归
            root.left = buildTree(leftInorder, leftPostorder);
            root.right = buildTree(rightInorder,rightPostorder);
            return 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 buildTree(int[] inorder, int[] postorder) {
            if (inorder.length == 0 || postorder.length == 0)
                return null;
            return traversal(inorder, 0, inorder.length, postorder, 0, postorder.length);
        }
    
        private TreeNode traversal(
            int[] inorder, int inorderBegin, int inorderEnd, 
            int[] postorder, int postorderBegin, int postorderEnd
            ) {
            if (postorderBegin == postorderEnd) return null;
            int rootValue = postorder[postorderEnd - 1];
            TreeNode root = new TreeNode(rootValue);
    
            if (postorderEnd - postorderBegin == 1) return root;
    
            int delimiterIndex;
            for (delimiterIndex = 0; delimiterIndex < inorder.length; delimiterIndex++) {
                if (inorder[delimiterIndex] == rootValue) 
                    break;
            }
            int leftInorderBegin = inorderBegin;
            int leftInorderEnd = delimiterIndex;
            int rightInorderBegin = delimiterIndex + 1;
            int rightInorderEnd = inorderEnd;
    
            int leftPostorderBegin = postorderBegin;
            int leftPostorderEnd = postorderBegin + leftInorderEnd - leftInorderBegin;
            int rightPostorderBegin = leftPostorderEnd;
            int rightPostorderEnd = postorderEnd - 1;
    
            root.left = traversal(
                inorder, leftInorderBegin, leftInorderEnd,
                postorder, leftPostorderBegin, leftPostorderEnd   
            );
            root.right = traversal(
                inorder, rightInorderBegin, rightInorderEnd,
                postorder, rightPostorderBegin, rightPostorderEnd
            );
            return root;
        }
    }
    
  • 相关阅读:
    博客园二号地址:
    VisionMaster4.0.0二次开发教程(每日更新博客)
    5.观察者模式
    4.策略模式
    微信小程序radio的样式修改
    Linux下mysql安装
    idea2020 设置Run Dashboard
    一个方便统计页面 PV/UV、触发和交互的轻量级前端埋点工具
    登录认证-实名认证-产品设计
    启示录—产品经理
  • 原文地址:https://www.cnblogs.com/PythonFCG/p/13887979.html
Copyright © 2011-2022 走看看