根据一棵树的两种遍历构造二叉树

古城微笑少年丶 2023-10-14 20:41 40阅读 0赞

c3e739057eae43d791dbf0769cde4d0e.jpeg

题目

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

示例 1:

d9af946559b84100a865d83ea5956dc0.jpeg

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

示例 2:

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

提示:

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

前置知识:

preorder :前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点—->根的左子树—->根的右子树。

inorder:中序遍历(Inorder Traversal)——根的左子树—->根节点—->根的右子树

前序遍历所得的第一个节点就是根节点,所以可以用来确定的是root根节点在中序遍历的位置,

再根据中序遍历,root根节点的左边是这棵二叉树的左树,root根节点的右边是这课二叉树的右树来构建这课二叉树

以示例1为例谈谈对题目的理解

示例1**输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]**

preorder = [ 3**, 9, 20, 15, 7 ] 3就为这棵二叉树的root根节点**

inorder = [ 9**, 3**, 15, 20, 7 ] 9为root的左树,并且只有一个节点,所以**9为root的左节点**

15,20,7这三个节点为root的右树,再根据中序遍历根的左子树—->根节点—->根的右子树可得

root的右节点为20**这个节点,20节点的左节点为15这个节点,**右节点为7这个节点

画图演示上述文字说明

6e0607488d334049a7eaf39975b407b0.png


解题思路:

根据题目所给的前序遍历的节点顺序在中序遍历中进行递归来构建二叉树

1.根据前序遍历找到中序遍历根节点iRoot的位置,创建根节点,再确定iBegin,iEnd的位置,i++;

2.对iBegin和iEnd的位置进行判断,当iBegin>iEnd时,返回null,递归开始回退;

2.在中序遍历当中,根据iRoot ,iBegin,iEnd的位置,并进行左树和右树的构建;

对上述三步进行递归,递归完了之后,二叉树构建完成,返回根节点root

注:对前序遍历所得节点的利用才是本题代码的灵魂所在

图示:


50768cc8c4fc4243b8fb6da5981e0e62.png

解题代码

  1. class Solution {
  2. public int i = 0;
  3. public TreeNode buildTree(int[] preorder, int[] inorder) {
  4. return create_a_binary_tree(preorder, inorder, 0, inorder.length - 1);
  5. }
  6. public TreeNode create_a_binary_tree(int[] preorder, int[] inorder, int inBegin, int inEnd) {
  7. if (inBegin > inEnd) {
  8. return null;
  9. //给定的数组int[] preorder, int[] inorder,遍历完了,没有子树了,该节点为空节点,返回null,递归开始回退
  10. }
  11. //先根据先序遍历创建根节点
  12. TreeNode root = new TreeNode(preorder[i]);
  13. //找到当前根节点,在中序遍历的位置
  14. int rootIndex = findIndex(inorder, inBegin, inEnd, preorder[i]);
  15. i++;
  16. //递归构建左树
  17. root.left = create_a_binary_tree(preorder, inorder, inBegin, rootIndex - 1);
  18. //递归构建右树
  19. root.right = create_a_binary_tree(preorder, inorder, rootIndex + 1, inEnd);
  20. //前序遍历完成,返回根节点
  21. return root;
  22. }
  23. private int findIndex(int[] inorder, int inBegin, int inEnd, int key) {
  24. for (int j = inBegin; j <= inEnd; j++) {
  25. if (inorder[j] == key) {
  26. return j;
  27. }
  28. }
  29. return -1;
  30. }
  31. }

运行结果

d8ef5a43492e41c4b4cf2dd220b7ae2f.png

题目链接

https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/submissions/

举一翻三,再来一道

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

给定两个整数数组 inorderpostorder ,其中 inorder 是二叉树的中序历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树

示例 1:

a08a616091b4403a83714357188a7086.jpeg

  1. 输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
  2. 输出:[3,9,20,null,null,15,7]

示例 2:

  1. 输入:inorder = [-1], postorder = [-1]
  2. 输出:[-1]

后序遍历(Postorder Traversal)——根的左子树—->根的右子树—->根节点。
创建根节点后,先创建右数,再创建左树

根据示例1进行讲解,下图是代码递归过程

8c1a8b673d2e436dac6715c944e16eac.png

随着代码的递归,二叉树随之构建的过程

9a838c3195cd4c0aa324559c50c5e112.png

解题代码

  1. public class Solution {
  2. public int i = 0;
  3. public TreeNode buildTree(int[] inorder, int[] postorder) {
  4. i = postorder.length - 1;
  5. return create_a_binary_tree(postorder, inorder, 0, inorder.length - 1);
  6. }
  7. public TreeNode create_a_binary_tree(int[] postorder, int[] inorder, int inBegin, int inEnd) {
  8. if (inBegin > inEnd) {
  9. return null;
  10. //给定的数组int[] postorder, int[] inorder,遍历完了,没有子树了,该节点为空节点,返回null,递归开始回退
  11. }
  12. //先根据先序遍历创建根节点
  13. TreeNode root = new TreeNode(postorder[i]);
  14. //找到当前根节点,在中序遍历的位置
  15. int rootIndex = findIndex(inorder, inBegin, inEnd, postorder[i]);
  16. i--;
  17. //递归先构建右树
  18. root.right = create_a_binary_tree(postorder, inorder, rootIndex + 1, inEnd);
  19. //递归后构建左树
  20. root.left = create_a_binary_tree(postorder, inorder, inBegin, rootIndex - 1);
  21. //前序遍历完成,返回根节点
  22. return root;
  23. }
  24. private int findIndex(int[] inorder, int inBegin, int inEnd, int key) {
  25. for (int j = inBegin; j <= inEnd; j++) {
  26. if (inorder[j] == key) {
  27. return j;
  28. }
  29. }
  30. return -1;
  31. }
  32. }

运行结果

e3535a97081742dfb699d5fc56c103a7.png

题目链接:

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

完结撒花✿✿ヽ(°▽°)ノ✿✿

ed60684c6baf4483a3542d8a0d0d137c.gif

发表评论

表情:
评论列表 (有 0 条评论,40人围观)

还没有评论,来说两句吧...

相关阅读

    相关 方式

    二叉树的遍历可分为两种 ''' 1.广度优先遍历 分层把元素放到 队列中,进行遍历 2.深度优先遍历 前序,中序,后序遍历,使用堆栈和递归的方式 '''

    相关 推出整

    二叉树由两种遍历推出整棵树 二叉树的先序,中序,后序遍历中,任意知道两种就可以推出整棵树长什么样。思路都是一样的,这里以先序和中序为例。 以下这个过程涉及到逆向推导,请