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


    题目

    给定两个整数数组 preorder 和 inorder ,其中 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]
    

    提示:

    • 1 <= preorder.length <= 3000
    • inorder.length == preorder.length
    • -3000 <= preorder[i], inorder[i] <= 3000
    • preorder 和 inorder 均 无重复 元素
    • inorder 均出现在 preorder
    • preorder 保证 为二叉树的前序遍历序列
    • inorder 保证 为二叉树的中序遍历序列

    解答

    源代码

    1. /**
    2. * Definition for a binary tree node.
    3. * public class TreeNode {
    4. * int val;
    5. * TreeNode left;
    6. * TreeNode right;
    7. * TreeNode() {}
    8. * TreeNode(int val) { this.val = val; }
    9. * TreeNode(int val, TreeNode left, TreeNode right) {
    10. * this.val = val;
    11. * this.left = left;
    12. * this.right = right;
    13. * }
    14. * }
    15. */
    16. class Solution {
    17. private Map indexMap;
    18. public TreeNode buildTree(int[] preorder, int[] inorder) {
    19. int n = preorder.length;
    20. indexMap = new HashMap();
    21. for (int i = 0; i < n; i++) {
    22. indexMap.put(inorder[i], i);
    23. }
    24. return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);
    25. }
    26. public TreeNode myBuildTree(int[] preorder, int[] inorder, int preorderLeft, int preorderRight, int inorderLeft, int inorderRight) {
    27. if (preorderLeft > preorderRight) {
    28. return null;
    29. }
    30. // 前序遍历的第一个节点就是根结点
    31. TreeNode root = new TreeNode(preorder[preorderLeft]);
    32. // 左子树节点数
    33. int leftSize = indexMap.get(preorder[preorderLeft]) - inorderLeft;
    34. int rightSize = inorderRight - indexMap.get(preorder[preorderLeft]);
    35. root.left = myBuildTree(preorder, inorder, preorderLeft + 1, preorderLeft + leftSize, inorderLeft, inorderLeft + leftSize - 1);
    36. root.right = myBuildTree(preorder, inorder, preorderLeft + leftSize + 1, preorderRight, inorderLeft + leftSize + 1, inorderRight);
    37. return root;
    38. }
    39. }

    总结

    对于任意一颗树而言,前序遍历的形式总是:

    [ 根节点, [左子树的前序遍历结果], [右子树的前序遍历结果] ]

    即根节点总是前序遍历中的第一个节点。而中序遍历的形式总是:

    [ [左子树的中序遍历结果], 根节点, [右子树的中序遍历结果] ]

    只要我们在中序遍历中定位到根节点,那么我们就可以分别知道左子树和右子树中的节点数目。由于同一颗子树的前序遍历和中序遍历的长度显然是相同的,因此我们就可以对应到前序遍历的结果中,对上述形式中的所有左右括号进行定位。

    这样以来,我们就知道了左子树的前序遍历和中序遍历结果,以及右子树的前序遍历和中序遍历结果,我们就可以递归地对构造出左子树和右子树,再将这两颗子树接到根节点的左右位置。

  • 相关阅读:
    axios设置请求头
    【ESP32_8266_WiFi (十三)】ESP8266自动配网 – WiFiManager库使用说明
    溶于乙醇的碳量子点CQDs,发射波长420nm,535nm,565nm,505nm,675nm
    Java之线程状态
    【C语言数据结构】空间复杂度和时间复杂度(详细分析)
    Docker 笔记
    网站页脚展示备案号并在新标签页中打开超链接
    【C语言进阶】动态内存管理及柔性数组
    树莓派pico mpu6050 一阶互补滤波&四元数法 解算姿态角
    04-SpringBoot的基础配置及其配置文件分类,解决Yaml文件失效问题
  • 原文地址:https://blog.csdn.net/qq_57438473/article/details/132650242