首页 > 其他分享 >【根据前序和中序遍历构造二叉树】栈+迭代 || 递归

【根据前序和中序遍历构造二叉树】栈+迭代 || 递归

时间:2024-04-20 17:44:25浏览次数:28  
标签:preorder 遍历 TreeNode int 中序 节点 二叉树 now 前序

105. 从前序与中序遍历序列构造二叉树

栈+迭代

规律

  • 前序遍历中相邻节点u和v,v节点一定是u节点的左节点或者是其自身某个祖先的右节点
  • 一个没有右节点的链,中序遍历是从叶子到根,前序遍历是从根到叶子

解题思路

  1. 用一个栈维护前序遍历的节点
  2. 用一个指针p指向中序遍历的第一个叶子节点
  3. 遍历前序,一直遍历到p指向的叶子节点,都持续是其父节点的左儿子,入栈即可。
  4. 若遍历到的节点的上一个节点为p指向的叶子节点,那么该节点就是树链(栈)上某个节点的右节点。如何找到其父亲?
  5. 使指针p在中序遍历上右移,同时在树链(栈)上回溯(弹栈),找到最后一个相同的节点,则为其父亲。
class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        TreeNode root = new TreeNode(preorder[0]);
        Stack<TreeNode> s = new Stack<>();
        s.push(root);
        int iIn = 0;
        TreeNode now = root;
        for(int i = 1; i < preorder.length; ++ i) {
            if(preorder[i - 1] != inorder[iIn]) {
                now.left = new TreeNode(preorder[i]);
                s.push(now.left);
                now = now.left;
            } else {
                while(!s.empty() && s.peek().val == inorder[iIn]) {
                    now = s.pop();
                    iIn ++ ;
                }
                now.right = new TreeNode(preorder[i]);
                s.push(now.right);
                now = now.right;
            }
        }
        return root;
    }
}

递归

  • 根节点在先序遍历中左右子树区间长度和在中序遍历中区间长度一致
  1. 先序遍历的子树区间第一个节点一定是根
  2. 定位中序遍历中根的位置,根的左子树区间在其左边,右子树区间在其右边,由此得到左右子树区间长度
  3. 由得到的左右子树区间长度来定位在先序遍历中的子树区间
  4. 再构建两棵子树,层层递归即可
class Solution {
    Map<Integer, Integer> map;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        map = new HashMap<>();
        for(int i = 0; i < inorder.length; ++ i ) {
            map.put(inorder[i], i);
        }
        return build(preorder, 0, preorder.length-1, 0, preorder.length-1);
    }

    public TreeNode build(int[] preorder, int preL, int preR, int inL, int inR) { // [preL, preR] [inL, inR]
        int val = preorder[preL];
        TreeNode root = new TreeNode(val);
        if(preL == preR) return root;
        int inId = map.get(val);
        int numL = inId - inL; // 左子树大小
        int numR = inR - inId; // 右子树大小

        if(numL > 0) root.left = build(preorder, preL + 1, preL + numL, inId - numL, inId - 1);
        if(numR > 0) root.right = build(preorder, preL + numL + 1, preR, inId + 1, inId + numR);

        return root;
    }
}

标签:preorder,遍历,TreeNode,int,中序,节点,二叉树,now,前序
From: https://www.cnblogs.com/Eve7Xu/p/18147910

相关文章

  • 给出二叉树的前序遍历和中序遍历--还原二叉树
    voidf(intidxroot){ //根据前序遍历和中序遍历还原二叉树if(idxroot==n+1)return;introot=pre[idxroot];boolcheck=true;map<int,int>lcmp,rcmp;//当前节点的左孩子集合和右孩子集合for(inti=1;i<=n;i++){if(vis[mid[i]]&&mid[i]!......
  • JZ32 从上往下打印二叉树
    /*structTreeNode{intval;structTreeNode*left;structTreeNode*right;TreeNode(intx):val(x),left(NULL),right(NULL){}};*/classSolution{public:vector<int>PrintFromTopToBottom(TreeNode*root){......
  • 树3-二叉树非递归遍历(栈)
    树3-二叉树非递归遍历(栈)拷贝根结点,初始值FALSE,入栈弹出,如果是FALSE,将根节点将更新为TRUE,其子结点(初始值FALSE)一并入栈[A,B,C](前序遍历,入栈顺序:C,B,A输出顺序:A,B,C)再弹出,如果是TRUE则输出引入链式栈头文件#include"linkedStack.h"链式栈头文......
  • JZ36二叉树排序树与双向链表
    /*structTreeNode{ intval; structTreeNode*left; structTreeNode*right; TreeNode(intx): val(x),left(NULL),right(NULL){ }};*/#include<cstddef>classSolution{public: TreeNode*ans=nullptr; //最终的链表 TreeNode*pre=nullptr; ......
  • 树1-二叉树概念与遍历方法
    树1:二叉树概念与遍历方法二叉树二叉树的遍历二叉树遍历分为前序,中序,后序.序是指遍历根结点的顺序D-data,根L左R右,先序遍历ABCDE-FGH中序遍历BDCE-A-FHG后序遍历DECB-HGF-A先序遍历ABDH-I-EJCFG中序遍历HDI-B-JEAFCG后序遍历HID-J......
  • 树2-二叉树拷贝, 遍历, 计算叶子结点和高度
    树2-二叉树拷贝,遍历,计算叶子结点和高度二叉树结点typedefstructBinaryNode{charch;structBinaryNode*lChild;structBinaryNode*rChild;}BinaryNode;//叶子结点的数量intsum;二叉树遍历前序//递归遍历(前序)voidRecursion(BinaryNode*roo......
  • 2024-04-17:用go语言,欢迎各位勇者莅临力扣城,本次的挑战游戏名为「力扣泡泡龙」。 游戏
    2024-04-17:用go语言,欢迎各位勇者莅临力扣城,本次的挑战游戏名为「力扣泡泡龙」。游戏的起点是一颗形状如二叉树的泡泡树,其中每个节点的值代表该泡泡的分值。勇者们有一次机会可以击破一个节点泡泡,但需要满足以下规则:被击破的节点泡泡最多只能有一个子节点泡泡。如果被击破的节点......
  • JZ27 二叉树的镜像
    /***structTreeNode{* intval;* structTreeNode*left;* structTreeNode*right;* TreeNode(intx):val(x),left(nullptr),right(nullptr){}*};*/classSolution{public:/***代码中的类名、方法名、参数名已经指定,请勿修改,直接返回......
  • JZ55 二叉树的深度
    /*structTreeNode{ intval; structTreeNode*left; structTreeNode*right; TreeNode(intx): val(x),left(NULL),right(NULL){ }};*/classSolution{public: //采用递归的方法intTreeDepth(TreeNode*pRoot){ //判空 if(pRoot==NULL) ......
  • 二叉树-层序遍历
    二叉树-层序遍历之前所述二叉树的递归遍历或者迭代遍历都属于深度优先搜索,即先迭代或者递归到树的某一枝最深处再逐渐回退,再到另一支的最深处再逐渐回退,从而完成遍历。而层序遍历属于广度优先遍历,即一层一层去遍历。需要借助队列辅助实现一层一层遍历的逻辑,因为其先进先出的逻辑......