重构二叉树

# 重构二叉树

1.前序遍历+中序遍历

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

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

img

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

思路

思路:
  1.我们知道前序遍历的第一个节点一定是当前子树的根节点,根节点后的一部分长度分别是左子树和右子树
  2.我们知道中序遍历的根节点在中间才会遍历到,根节点左边部分为其左子树,根节点右边部分为其右子树
  3.由于题目中不会出现两个节点的值相同,我们可以根据前序遍历中的根节点(即第一个节点)找到其在中序遍历中的位置

在这里插入图片描述

	4.为了加快查找的速度,我们可以将中序序例的值以及Index放入map中,并且我们将在中序遍历中找到的根节点下标记为pIndex
  5.上述我们可以计算出左子树的长度为pIndex-inLeft;因此对应到前序遍历序例中左子树的终止位置
  6.据上述条件,我们就可以分别计算出左右子树对应的起始位置,终止位置;进行递归调用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YEM5R1UB-1662790283636)(/Users/lanqian/Desktop/屏幕快照 2022-09-10 下午11.34.58 上午.png)]

	7.考虑basecase:当左子树的右边界小于左边界时,返回null;
  							 当左子树的右边界等于做边界时,直接返回当前节点,此节点为叶子节点了
    						 右子树同理

代码

import java.util.HashMap;

public class Solution {

     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;
     }
 }
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        int preLength=preorder.length;
        int inLength=inorder.length;

        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < inLength; i++) {
            map.put(inorder[i],i);
        }
        
        return buildTree(preorder,0,preLength-1,map,0,inLength-1);
    }

    private TreeNode buildTree(int[] preorder, int preLeft, int preRight, HashMap<Integer, Integer> map, int inLeft, int inRight) {
        if(preLeft>preRight || inLeft>inRight){
            return null;
        }

        if(preLeft==preRight || inLeft==inRight)return new TreeNode(preorder[preLeft]);
        
        Integer pIndex = map.get(preorder[preLeft]);
        TreeNode node = new TreeNode(preorder[preLeft]);
        node.left=buildTree(preorder,preLeft+1,preLeft+pIndex-inLeft,map,inLeft,pIndex-1);
        node.right=buildTree(preorder,preLeft+pIndex-inLeft+1,preRight,map,pIndex+1,inRight);
        return node;
    }
}

2.前序遍历+后序遍历

给定两个整数数组,preorder 和 postorder ,其中 preorder 是一个具有 无重复 值的二叉树的前序遍历,postorder 是同一棵树的后序遍历,重构并返回二叉树。

如果存在多个答案,您可以返回其中 任何 一个。

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

输入:preorder = [1,2,4,5,3,6,7], postorder = [4,5,2,6,7,3,1]
输出:[1,2,3,4,5,6,7]

img

思路

思路:
  1.我们知道前序遍历的第一个节点一定是当前子树的根节点,根节点后的一部分长度分别是左子树和右子树
  2.后序遍历的最后一个节点为当前子树的根节点,其前一部分为右子树,最开始部分为左子树部分

	3.前序遍历中的第二个节点即为左子树的根节点,且题目中每个节点的值各不相同,我们也可以在后序遍历中找出对应的左子树根节点的位置记为pIndex
  4.左子树的长度为pIndex-postLeft+1(注意这里的+1与从前序和中序的结果不同,这里的pIndex位置是属于左子树的,而前序和中序中pIndex是属于根节点的不在左子树的序列中)
  5.由于左子树长度是相等的我们可以计算出对饮的前序遍历中左子树的起始位置和终止位置
  6.右子树同理 

代码

import java.util.HashMap;

public class Solution {
     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;
     }
 }

    public TreeNode constructFromPrePost(int[] preorder, int[] postorder) {
        int preLength=preorder.length;
        int postLength=postorder.length;
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < postorder.length; i++) {
            map.put(postorder[i],i);
        }
        return constructFromPrePost(preorder,0,preLength-1,map,0,postLength-1);
    }

    private TreeNode constructFromPrePost(int[] preorder, int preLeft, int preRight, HashMap<Integer, Integer> map, int postLeft, int postRight) {
         if(preLeft>preRight || postLeft>postRight)return null;
         if(preLeft==preRight || postLeft==postRight)return new TreeNode(preorder[preLeft]);

        Integer pIndex = map.get(preorder[preLeft + 1]);
        TreeNode node = new TreeNode(preorder[preLeft]);
        node.left=constructFromPrePost(preorder,preLeft+1,preLeft+pIndex-postLeft+1,map,postLeft,pIndex);
        node.right=constructFromPrePost(preorder,preLeft+pIndex-postLeft+2,preRight,map,pIndex+1,postRight);
        return node;
    }
}

3.中序遍历+后序遍历

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

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

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

img

思路

思路:
  1.后序遍历的最后一个节点为当前子树的根节点,其前一部分为右子树,最开始部分为左子树部分
  2.由于节点的值不重复,我们可以将中序遍历的值存入map,查处后序遍历中最后一个节点在中序遍历中的位置,记为pIndex
  3.得出各个下标如图

代码

class Solution {
 public TreeNode buildTree(int[] inorder, int[] postorder) {
        int inLen=inorder.length;
        int postLen=postorder.length;
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < inLen; i++) {
            map.put(inorder[i],i);
        }
        return buildTree(postorder,0,postLen-1,map,0,inLen-1);
    }

    private static TreeNode buildTree(int[] postorder, int postLeft, int postRight, HashMap<Integer, Integer> map,
                               int inLeft, int inRight) {
        if(postLeft>postRight || inLeft>inRight){
            return null;
        }
         if(postLeft==postRight)return new TreeNode(postorder[postLeft]);

        TreeNode node = new TreeNode(postorder[postRight]);
        Integer pIndex = map.get(postorder[postRight]);

        node.left=buildTree(postorder,postLeft,pIndex-inLeft+postLeft-1,map,inLeft,pIndex-1);
        node.right=buildTree(postorder,pIndex-inLeft+postLeft,postRight-1,map,pIndex+1,inRight);

        return node;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值